Home/ Blog/ Plotting Rolling Graph on OLED

Arduino Β· OLED

Plotting Rolling Graph on OLED

✍️ Vivekanand Dhakane πŸ“… Dec 5, 2022 ⏱ 4 min read πŸ‘ 1,519 views
← Back to Blog

In this blog, we will see how to plot a rolling graph on an OLED display. For this tutorial, we will use a 0.96" OLED display with an SSD1306 driver. We will use Arduino, but the algorithm is the same for other controllers.

Single sine wave rolling on OLED

Single sine wave output

Rolling sine wave on OLED display

Rolling sine wave displayed on 0.96" OLED

β–Ά Watch the video tutorial on YouTube

Basics

Now let's start from the basics

Let's start from the basics. The 0.96" OLED has 128Γ—64 pixels. It has one special feature: the ability to scroll/roll display content from left to right and right to left. This feature is very useful for plotting a rolling graph.

Because of this, we need to plot only one point on the rightmost pixel column, and then that point is rolled by the display driver from right to left β€” without needing the controller to do any shifting.

πŸ’‘ The controller's task is to put a point on the rightmost column of pixels. The display driver will take care of rolling that point from right to left automatically.

Calculating Time Interval

Pixels added and rolling on the screen animation

Pixels added and rolling on the screen

In the OLED display, we can set the rolling speed to 8 levels (0 to 7). Consider we want to draw a rolling sine wave on the display. First, we plot a single pixel on the right-most pixel column. Then this pixel column is shifted left by the display controller. Then we need to plot the next point on the same rightmost pixel column.

But for that, we need to know how much time it takes to shift by one pixel for all 8 levels of speed. The following code is used to measure the time taken by a single pixel to shift by one pixel to the left.

void setup() {
  Serial.begin(9600);
  oled_begin();
  set_pixal(0, 32);
  scrollLeft(0x00, 0x07, 0x07);
}

Output of above code:

Single pixel traveling from right to left

A single pixel traveling from right to left

Time interval calculation formula

To measure the time accurately: measure the time required for a single pixel to travel the full width (128 pixels) 10 times, then divide by 10 to get the average time for single-width travel with less error. Dividing by 128 gives the time for a single pixel shift (Ξ”T).

Speed vs. Timing Table

Speed versus pixel shift time table

Time taken for pixel shift at each speed level

Speed Level T1 (10Γ— width) sec T2 = T1/10 sec Ξ”T = T2/128 ms
7232.318
4353.527.3
5464.636
657.55.7545
070754.7
137037289
274074586
314801481156

Now we have the time intervals. Here's the key data arrays used in code:

byte select_speed[] = {3,2,1,0,6,5,4,7};
int  sampling_period[] = {1150,580,280,50,40,33,24,14};
float TimeScale[] = {148,74,37,7,5.75,4.6,3.5,2.3};

The set_pixal() Function

The set_pixal() function lights up an individual pixel at a given (x, y) coordinate. Our rolling plot is made from such single pixels.

void set_pixal(byte x_cord, byte y_cord)
{
  byte x_mod, y_mod, pixel_location, data, y_mod_page;
  y_cord = 63 - y_cord;
  x_mod = x_cord;
  y_mod_page = (y_cord) / 8;
  pixel_location = y_cord % 8;
  data = 0B00000001 << pixel_location;
  setCursor(x_mod, y_mod_page);
  writeData(data);
}

Timer Interrupt

We need to put a pixel on the rightmost pixel column at specific intervals of time β€” and this interval must be followed accurately.

This mismatch in sampling time causes an unwanted out-of-phase sine wave to appear alongside the intended wave:

Out-of-phase sine wave due to wrong sampling time

Wrong sampling β†’ out-of-phase wave

To achieve accurate sampling, we use a Timer interrupt β€” specifically MsTimer2. (Timer1 cannot be used when the I2C bus is active for the display.)

Code Flow

Code flow diagram

Code flow diagram

Just to keep things simple, the sine wave is generated in the controller (Arduino) itself using the formula x = AΒ·sin(2Ο€t/T) + offset. A count variable holds the current sample value, set by the timer interrupt, then plotted using set_pixal().

// setup function and OLED configuration functions not shown here

void timerIsr() // Timer interrupt function
{
  get_sample = true;
}

void loop() {
  float seconds = millis() / 1000.0;

  // Sine wave generated in count variable
  // Formula: x = A sin(2Ο€t/T) + offset
  count = 18 * sin(2 * PI * (seconds / 4.6)) + 28;

  if (get_sample) // get_sample is set TRUE by timer interrupt
  {
    // First clear the column
    for (byte i = 1; i < 8; i++)
    {
      setCursor(127, i);
      writeData(0x00); // clear the column of 8 pixels
    }
    // Now plot the point
    set_pixal(127, count);
    get_sample = false;
  }
}

Output

Single sine wave rolling on OLED

Single sine wave output (Time = 4.6 sec full width)

Adding Multiple Waves

We can add multiple waves by calling set_pixal() for each wave:

//Sine wave generated in count variable
//Formula : x = A sin(2Ο€t/T)+ offset
  count = 18 * sin(2 * PI * (seconds / 4.6)) + 28; //wave 1
  count2 =18 * sin(PI+2*PI*(seconds/4.6))+ 28;     //wave 2
            .
            .
            .
  set_pixal(127, count);    //wave 1
  set_pixal(127, count2);   //wave 2
            .
            .
            .
Final rolling graph with time scale on OLED

Final result β€” rolling graph on OLED (Time = 4.6 SEC = full display width)

In the above image, Time = 4.6 SEC is the time scale for the full display width.

Download Arduino Code

Download Arduino Code from GitHub

In this way we can display any signal on the OLED display. Please let me know your thoughts in the comment section!

← An RTPCR Machine All Posts β†’

Comments