HomeArduino TutorialsArduino Displays & InterfacesArduino ST7920 Graphics Guide: How to Create Scrolling Text, Animations and Page Transitions (U8g2)

ST7920 Arduino Tutorial (Part 3): Scrolling, Animations & Smooth Screen Transitions with U8g2

Welcome to the third part of the ST7920 Arduino Tutorial series.
In the previous two guides, you learned how to connect the ST7920 128×64 display, print text, and draw graphics using the U8g2 library. Now it is time to take your UI to the next level.

In this tutorial, you will learn how to create scrolling text, smooth animations, and professional screen transitions on the ST7920 display. These effects help your project look modern, alive, and more interactive.

By the end of this guide, you will be able to create animated menus, moving icons, loading screens, progress bars, sliding pages, and much more using Arduino and U8g2.

Prerequisites:

You must go through the previous 2 parts of this mini series:

ST7920 Arduino Tutorial Scrolling, Animations & Smooth Screen Transitions with U8g2

Scrolling Text on ST7920 using Arduino and U8g2

The Scrolling text is one of the most common effects used in modern displays. It helps when the message is longer than the screen width, or when you want to create attention-grabbing UI elements like headlines, tickers, and alerts. In this part, you will learn how to create smooth horizontal scrolling, vertical scrolling, and a marquee banner using the ST7920 display with the U8g2 library. These effects make even a simple monochrome screen look dynamic and professional.

Horizontal Scrolling Text (Left to Right / Right to Left)

Below is a fully working version with the correct scrolling behavior. This code uses a fixed frame rate and calculates the text width properly. It scrolls from right to left, which is the most common style.

Below is the Code for Horizontal Scrolling Text

#include <Arduino.h>
#include <U8g2lib.h>
#include <SPI.h>

// ST7920 128x64 using Software SPI
U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* CS=*/ 10, /* reset=*/ 8);

const char msg[] = "Controllerstech Tutorials";
int displayWidth = 128;     // ST7920 width in pixels
int textWidth;              // Pixel width of the message
int xPos;                   // Current X position of the text

unsigned long lastMillis = 0;
const unsigned long frameDelay = 40;

void setup() {
  u8g2.begin();
  u8g2.setFont(u8g2_font_6x12_tf);

  // Measure text width after setting the font
  textWidth = u8g2.getStrWidth(msg);

  // Start the text just outside the right edge
  xPos = displayWidth;
}

void loop() {
  // Maintain stable frame timing
  if (millis() - lastMillis < frameDelay) return;
  lastMillis = millis();

  u8g2.firstPage();
  do {
    u8g2.drawStr(xPos, 32, msg);   // Draw text horizontally centered
  } while (u8g2.nextPage());

  // Move text left
  xPos--;

  // When text moves fully off the left side, reset it to the right side
  if (xPos < -textWidth) {
    xPos = displayWidth;
  }
}

Explanation

This example creates a smooth right-to-left scrolling effect. The text begins from the right edge of the screen and moves left one pixel at a time.

  • The getStrWidth() function is used to calculate the exact pixel width of the string. This is very important, because different fonts have different character widths. If the text width is not calculated properly, the scroll will stop early or will not reset correctly.
  • Once the text has moved completely off the screen (i.e., its rightmost pixel is past the left edge), we reset the xPos back to the full display width. This makes the scrolling continuous. The controlled frame delay ensures smooth animation without flicker.

Output

The gif below shows the text smoothly sliding from right to left across the display.

gif showing scrolling text on ST7920 graphic LCD, which is connected to Arduino via SPI.

Vertical Scrolling Text (Up and Down)

Scrolling Vertical is useful for showing notifications, credits, or long descriptions in a limited vertical space. In this example, the text moves from the bottom of the screen toward the top.

Below is the Code to scroll text Vertically

#include <Arduino.h>
#include <U8g2lib.h>
#include <SPI.h>

U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, 13, 11, 10, 8);

int yPos = 64;                     // Start from bottom edge
const char* vText = "Scrolling Vertically";
const unsigned long frameDelay = 40;

void setup() {
  u8g2.begin();
  u8g2.setFont(u8g2_font_6x12_tf);
}

void loop() {
  u8g2.firstPage();
  do {
    u8g2.drawStr(10, yPos, vText);
  } while (u8g2.nextPage());

  yPos--;

  // Reset once the text scrolls out of view
  if (yPos < -10) {
    yPos = 64;
  }

  delay(frameDelay);
}

Explanation

The vertical scrolling effect works by gradually decreasing the y-coordinate of the text. The text starts at the bottom of the screen (y = 64) and moves upward one pixel at a time.

Once the text moves completely out of the top boundary, we reset the position back to the bottom. Vertical scroll effects are commonly used in menus, messages, and scrolling credits. This type of motion also gives a “smooth lift” feel, which is very helpful in UI navigation.


Output

The gif below shows the text moving upward smoothly, creating a clean vertical scrolling effect.

gif showing scrolling text on ST7920 graphic LCD, which is connected to Arduino via SPI.

Marquee Banner Effect for Headlines

A marquee banner is commonly used for alerts, news tickers, and headline strips. In this effect, the top area of the display is turned into a moving banner with bold text. This enhances readability and draws user attention.

Below is the Code for Marquee Banner Text (with seamless scroll)

#include <Arduino.h>
#include <U8g2lib.h>
#include <SPI.h>

U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, 13, 11, 10, 8);

const char* banner = " Welcome to Controllerstech ";
int textWidth;
int xPos = 0;
const int displayWidth = 128;

unsigned long lastMillis = 0;
const unsigned long frameDelay = 35;

void setup() {
  u8g2.begin();
  u8g2.setFont(u8g2_font_7x14B_tf);   // Bold font for banner
  textWidth = u8g2.getStrWidth(banner);
}

void loop() {
  if (millis() - lastMillis < frameDelay) return;
  lastMillis = millis();

  u8g2.firstPage();
  do {
    // Draw banner background
    u8g2.drawBox(0, 0, 128, 16);

    // Draw two copies of the text for seamless scrolling
    u8g2.setDrawColor(0); // White text on black
    u8g2.drawStr(xPos, 14, banner);
    u8g2.drawStr(xPos + textWidth, 14, banner);
    u8g2.setDrawColor(1);
  } while (u8g2.nextPage());

  xPos--;

  // Seamless reset
  if (xPos <= -textWidth) {
    xPos += textWidth;
  }
}

Explanation

This code creates a professional-looking marquee banner, just like the scrolling headlines on news channels. The banner area is drawn using a solid black rectangle, and bold white text scrolls through it.

To achieve a seamless effect without any blank gaps, two copies of the string are drawn:

  • one at xPos
  • another at xPos + textWidth

As the first text scrolls off the screen, the second one takes its place. This gives the illusion of a continuous loop, making the banner look smooth and polished.

The bold font enhances visibility, and the dark background makes the banner stand out from the rest of the screen.


Output

The gif below shows the marquee banner on the display.

gif showing marquee text on ST7920 graphic LCD, which is connected to Arduino via SPI.

Creating Animations on ST7920 with Arduino

Animations make the UI feel alive, modern and professional. Even on a small monochrome display like the ST7920, you can create smooth motion effects using simple logic and the U8g2 library.
In this section, we will explore different animation styles, from frame-by-frame animation to sliding banners and progress bars.

Frame-by-Frame Animation Example

Frame-by-frame animation is the simplest form of animation. You draw individual frames and show them one after another with a delay. This technique works well for icons, emoji-style graphics, or simple motion.

Below is the Code to draw Frame-by-Frame Animation

#include <U8g2lib.h>
#include <Wire.h>

// Using 128x64 ST7920 SPI
U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, 13, 11, 10, 8);

const unsigned char frame1[] PROGMEM = {
  0x00,0x18,0x3C,0x7E,0x3C,0x18,0x00
};

const unsigned char frame2[] PROGMEM = {
  0x00,0x0C,0x1E,0x3F,0x1E,0x0C,0x00
};

void setup() {
  u8g2.begin();
}

void loop() {
  u8g2.firstPage();
  do {
    u8g2.drawXBMP(60, 24, 7, 7, frame1);
  } while (u8g2.nextPage());
  delay(150);

  u8g2.firstPage();
  do {
    u8g2.drawXBMP(60, 24, 7, 7, frame2);
  } while (u8g2.nextPage());
  delay(150);
}

Explanation

This example stores two small bitmap frames in PROGMEM. The display shows frame1, waits a moment, then shows frame2, creating a blinking or beating effect.
By adding more frames, you can create smoother animations.


Output

The gif below shows the frame-by-frame animation on the display.

gif showing frame-by-frame animation on ST7920 graphic LCD, which is connected to Arduino via SPI.

Moving Object Animation (Ball / Icon Movement)

This effect moves an object smoothly across the screen. It is great for indicators, UI elements, bouncing objects, or simple games.

Below is the Code for Moving Ball Animation

#include <U8g2lib.h>
#include <Wire.h>

U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, 13, 11, 10, 8);

int x = 0;
int y = 30;
int speedX = 2;

void setup() {
  u8g2.begin();
}

void loop() {
  x += speedX;

  if (x > 120 || x < 0) {
    speedX = -speedX; // bounce
  }

  u8g2.firstPage();
  do {
    u8g2.drawDisc(x, y, 5, U8G2_DRAW_ALL);
  } while (u8g2.nextPage());

  delay(50);
}

Explanation

A simple physics loop updates the x-position of the ball. When the ball reaches a screen edge, the direction reverses, creating a bouncing animation.
This is one of the smoothest animation styles on ST7920 because drawing a circle is fast.


Output

The gif below shows the output of the moving ball animation.

gif showing moving ball animation on ST7920 graphic LCD, which is connected to Arduino via SPI.

Loading Spinner Animation

The Loading spinners give a modern look and are useful for processes like reading sensors or loading menus.

Below is the Code fo Loading Spinner

#include <U8g2lib.h>

U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, 13, 11, 10, 8);

int angle = 0;

void setup() {
  u8g2.begin();
}

void loop() {
  u8g2.firstPage();
  do {
    int x = 64 + 20 * cos(angle * 0.1);
    int y = 32 + 20 * sin(angle * 0.1);

    u8g2.drawCircle(64, 32, 22);
    u8g2.drawDisc(x, y, 3);
  } while (u8g2.nextPage());

  angle++;
  if (angle > 360) angle = 0;

  delay(30);
}

Explanation

This spinner uses trigonometric functions to move a small dot around a circular path. The outer circle stays fixed, while the dot rotates smoothly like a loading icon found in modern apps.


Output

The image below shows a spinning loader animation with a dot rotating around a circle.

gif showing loading spinner animation on ST7920 graphic LCD, which is connected to Arduino via SPI.

Progress Bar Animation

The Progress bars are useful for showing loading tasks, sensor calibration, or startup screens.

Below is the Code for Progress Bar Animation.

#include <U8g2lib.h>

U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, 13, 11, 10, 8);

int progress = 0;

void setup() {
  u8g2.begin();
}

void loop() {
  progress++;
  if (progress > 100) progress = 0;

  u8g2.firstPage();
  do {
    u8g2.drawFrame(20, 30, 88, 12);   // outline
    u8g2.drawBox(22, 32, progress * 0.84, 8);
  } while (u8g2.nextPage());

  delay(60);
}

Explanation

The bar grows gradually from 0% to 100%. To convert percentage into pixel width, the code multiplies by 0.84 because the bar width is 84 pixels.
This makes a smooth and clean loading bar animation.


Output

The gif below shows the progress bar animation.

gif showing Progress bar animation on ST7920 graphic LCD, which is connected to Arduino via SPI.

Screen Transitions for ST7920 UI Navigation

Modern user interfaces feel smooth because screens do not change suddenly. Instead, they use transitions — sliding, fading, or soft switching. Even with a monochrome display like the ST7920, you can create clean and attractive page transitions using the U8g2 library.

In this section, we will create three useful transitions that you can use for menus, dashboards, or multi-page UI.

Slide Left and Slide Right Transition

A sliding transition makes the next page appear as if it is moving from one side of the screen. This is one of the most common UI effects seen in mobile apps and smart displays.

Below is the Code for Slide Left / Slide Right Page Transition

#include <U8g2lib.h>

U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, 13, 11, 10, 8);

int offset = 0;
bool nextPage = false;

void drawPage1(int x) {
  u8g2.setFont(u8g2_font_6x10_tf);
  u8g2.drawStr(x + 10, 20, "PAGE 1");
  u8g2.drawStr(x + 10, 40, "This is the first screen");
}

void drawPage2(int x) {
  u8g2.setFont(u8g2_font_6x10_tf);
  u8g2.drawStr(x + 10, 20, "PAGE 2");
  u8g2.drawStr(x + 10, 40, "Welcome to the next page");
}

void setup() {
  u8g2.begin();
}

void loop() {

  if (!nextPage) {
    // ---- Slide Left (Page 1 → Page 2) ----
    for (offset = 0; offset >= -128; offset -= 8) {
      u8g2.firstPage();
      do {
        drawPage1(offset);
        drawPage2(offset + 128);
      } while (u8g2.nextPage());
      delay(40);
    }
    nextPage = true;
    delay(1000);
  } 
  else {
    // ---- Slide Right (Page 2 → Page 1) ----
    for (offset = -128; offset <= 0; offset += 8) {
      u8g2.firstPage();
      do {
        drawPage1(offset);
        drawPage2(offset + 128);
      } while (u8g2.nextPage());
      delay(40);
    }
    nextPage = false;
    delay(1000);
  }
}

Explanation

This effect creates two virtual pages.

  • By shifting both pages horizontally at the same speed, one page slides out while the other slides in.
  • Sliding left shows the next page. Sliding right returns to the previous page.
  • The animation is smooth because each step moves only a few pixels.

Output

The gif below shows the Slide Left / Slide Right Page Transition.

gif showing screen transition effect on ST7920 graphic LCD, which is connected to Arduino via SPI.

Fade Effect using Gradual Clear

A fade-out effect is easy to simulate on monochrome displays. The trick is to slowly clear different parts of the screen, giving a smooth visual transition.

Below is the Code for Fade-Out Transition

#include <U8g2lib.h>

U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, 13, 11, 10, 8);

void drawPage() {
  u8g2.setFont(u8g2_font_6x10_tf);
  u8g2.drawStr(20, 30, "Fading Page...");
}

void setup() {
  u8g2.begin();
}

void loop() {

  // Draw the full page
  u8g2.firstPage();
  do {
    drawPage();
  } while (u8g2.nextPage());

  delay(1000);

  // ---- Gradual Fade ----
  for (int i = 0; i < 64; i += 4) {
    u8g2.firstPage();
    do {
      drawPage();               // redraw page
      u8g2.setDrawColor(0);     // set color to erase
      u8g2.drawBox(0, i, 128, 4); // clear strip
      u8g2.setDrawColor(1);
    } while (u8g2.nextPage());
    delay(40);
  }

  delay(800);
}

Explanation

The page is displayed normally. Then, each loop clears a horizontal strip of the display. Because the stripping happens slowly, the page appears to fade away, line by line.

You can reverse the logic to create a fade-in effect as well.


Output

The gif below shows the Fade-Out Transition.

gif showing fading page effect on ST7920 graphic LCD, which is connected to Arduino via SPI.

Smooth Page Switching Technique

If you do not want sliding or fading, you can use a gentle soft switch. This draws a small fade at the top or bottom, creating a subtle transition.

Below is the Code for Smooth Page Switch

#include <U8g2lib.h>

U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, 13, 11, 10, 8);

void drawPageA() {
  u8g2.setFont(u8g2_font_6x10_tf);
  u8g2.drawStr(10, 25, "This is PAGE A");
}

void drawPageB() {
  u8g2.setFont(u8g2_font_6x10_tf);
  u8g2.drawStr(10, 25, "This is PAGE B");
}

void setup() {
  u8g2.begin();
}

void softSwitch(void (*pageA)(), void (*pageB)()) {
  // Fade bottom up
  for (int h = 0; h <= 64; h += 6) {
    u8g2.firstPage();
    do {
      pageA();
      u8g2.setDrawColor(0);
      u8g2.drawBox(0, 64 - h, 128, h);
      u8g2.setDrawColor(1);
    } while (u8g2.nextPage());
    delay(40);
  }

  // Fade-in next page
  for (int h = 64; h >= 0; h -= 6) {
    u8g2.firstPage();
    do {
      pageB();
      u8g2.setDrawColor(0);
      u8g2.drawBox(0, 0, 128, h);
      u8g2.setDrawColor(1);
    } while (u8g2.nextPage());
    delay(40);
  }
}

void loop() {
  softSwitch(drawPageA, drawPageB);
  delay(1000);
  softSwitch(drawPageB, drawPageA);
  delay(1000);
}

Explanation

  • This function clears the previous page from bottom to top.
  • Then it shows the next page gradually from top to bottom.
  • The effect is very smooth and soft, giving a premium UI feeling.

The transition does not move fast and does not feel abrupt, making it perfect for menu screens.


Output

The image below shows a gentle fade transition between Page A and Page B.

gif showing smooth page transition on ST7920 graphic LCD, which is connected to Arduino via SPI.

Practical Animation Examples for ST7920

This section brings everything together. Here, we turn animation concepts into real UI designs for the ST7920 display. You will learn how to animate a logo, make a simple clock animation, and generate a smooth waveform using the sin() function.
These examples will help you build professional-looking interfaces for your Arduino projects.

Logo Animation (Move, Scale or Reveal)

Logo animations make your project feel branded and polished. In this example, we reveal the logo by sliding it from left to right.

Below is the Code for Logo Reveal Animation

#include <U8g2lib.h>

U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, 13, 11, 10, 8);

// Simple 32x16 logo bitmap (replace with your actual logo)
const unsigned char logoBitMap[] PROGMEM = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0xe0, 0xff, 0x01, 
	0x00, 0xf8, 0xff, 0x07, 0x00, 0xee, 0xff, 0x0f, 0x00, 0xbb, 0xfd, 0x3f, 0x80, 0xed, 0x77, 0x38, 
	0xc0, 0xb6, 0x1d, 0x60, 0x60, 0xdb, 0x06, 0xc0, 0xb0, 0x6d, 0x03, 0x80, 0xdc, 0xb6, 0x01, 0x00, 
	0x74, 0xdf, 0x60, 0x40, 0xbc, 0x6f, 0x50, 0xa4, 0xd8, 0x3e, 0x70, 0xea, 0x68, 0x18, 0x10, 0x2e, 
	0x7e, 0x18, 0x08, 0x12, 0x77, 0x0e, 0x34, 0x09, 0x35, 0x0f, 0x92, 0x1c, 0x02, 0x06, 0xfb, 0x2e, 
	0x00, 0x80, 0x6d, 0x3b, 0x00, 0xc0, 0xb6, 0x0d, 0x02, 0x60, 0xdb, 0x06, 0x06, 0x90, 0x6d, 0x03, 
	0x1c, 0x6c, 0xb2, 0x01, 0xf8, 0xbb, 0xc9, 0x00, 0xf0, 0x7f, 0x36, 0x00, 0xe0, 0xff, 0x1d, 0x00, 
	0x80, 0xff, 0x07, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

int xPos = -40;   // start outside screen

void setup() {
  u8g2.begin();
}

void loop() {
  xPos += 4;

  if (xPos > 48) xPos = -40;  // reset and repeat

  u8g2.firstPage();
  do {
    u8g2.drawXBMP(xPos, 24, 32, 32, logoBitMap);
  } while (u8g2.nextPage());

  delay(60);
}

Explanation

The logo begins off-screen at x = -40.

  • It moves smoothly until it reaches the center area of the display.
  • When it goes too far, the position resets and the animation repeats.
  • You can replace the bitmap with your real logo and adjust movement or scaling.

Output

The gif below shows the Logo reveal effect on the display.

gif showing Logo reveal animation on ST7920 graphic LCD, which is connected to Arduino via SPI.

Simple Clock Animation

A clock animation shows how useful dynamic UI elements can be. Here, we animate the second hand of a minimal analog clock.

Below is the Code for animated Clock Example

#include <U8g2lib.h>
#include <math.h>

U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, 13, 11, 10, 8);

int secAngle = 0;  // angle for second hand

void setup() {
  u8g2.begin();
}

void loop() {

  int centerX = 64;
  int centerY = 32;
  int radius = 20;

  // second hand end point
  int x = centerX + radius * cos(secAngle * 0.10472);  // convert secAngle to radians
  int y = centerY + radius * sin(secAngle * 0.10472);

  secAngle++;
  if (secAngle >= 60) secAngle = 0;

  u8g2.firstPage();
  do {
    u8g2.drawCircle(centerX, centerY, radius);
    u8g2.drawLine(centerX, centerY, x, y);
  } while (u8g2.nextPage());

  delay(200);
}

Explanation

This code draws a static circle representing the clock face.

  • Only the second hand changes — its angle updates every loop.
  • To convert 60 seconds into 360 degrees, we multiply by 0.10472 radians per second.
  • The result is a clean, smooth second-hand animation.

Output

The gif below shows the clock animation on the display.

gif showing Clock animation on ST7920 graphic LCD, which is connected to Arduino via SPI.

Waveform Animation using sin() Function

Waveforms are perfect for audio-style displays, sensor visualization, and oscilloscopes. Using the sin() function gives you a smooth, professional curve.

Below is the Code for Live Waveform Animation

#include <U8g2lib.h>
#include <math.h>

U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, 13, 11, 10, 8);

float phase = 0;

void setup() {
  u8g2.begin();
}

void loop() {

  u8g2.firstPage();
  do {
    for (int x = 0; x < 128; x++) {
      float yVal = 32 + 20 * sin((x * 0.15) + phase);
      u8g2.drawPixel(x, (int)yVal);
    }
  } while (u8g2.nextPage());

  phase += 0.2;   // shift waveform horizontally
  if (phase > 1000) phase = 0;

  delay(40);
}

Explanation

  • Each x pixel is used as an input to the sine function.
  • The sine result determines the y pixel position, forming a smooth wave.
  • By increasing phase, the wave moves left or right, creating a real-time waveform animation.

You can adjust:

  • amplitude (wave height)
  • frequency (wave tightness)
  • speed (phase jump)

Output

The gif below shows the waveform animation on the display.

gif showing Waveform animation on ST7920 graphic LCD, which is connected to Arduino via SPI.

Conclusion

In this tutorial, you learned how to take the ST7920 display far beyond static images and simple text. By using the power of the U8g2 library, you created smooth scrolling text, clean animations, and modern screen transitions that bring your UI to life. These techniques give your projects a polished, professional feel, something normally seen in advanced embedded systems.

You explored horizontal and vertical scrolling, marquee banners, logo reveal effects, waveform animations, loading spinners, progress bars, and multiple styles of page transitions.
Each example helps you understand how movement works on a monochrome display and how small changes in position, timing, and redrawing can create powerful effects.

With these skills, you can now build:

  • Multi-page menus
  • Animated dashboards
  • Branded boot screens
  • Real-time data visualizers
  • Interactive embedded UIs

The ST7920 may look simple, but with the right animations, it becomes a flexible display capable of delivering a rich user experience. Feel free to combine and customize these techniques to create your own style of interface.

Browse More Arduino Display Tutorials

Arduino ST7920 Project Download

Info

You can help with the development by DONATING Below.
To download the project, click the DOWNLOAD button.

Arduino ST7920 Animations FAQs

Subscribe
Notify of

0 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments