Performance advice for random noise on 128x32px OLED display

Hi!

I'm trying to display random noise on one of those I2C 0.91 inch 128x32 OLED screens and with my current code I seem to have so much overhead that I can only refresh it about every 450 ms.

Right now I'm using an Arduino Uno for development, but ideally I'd later convert it for use on an ATTiny.

Any chance that someone could point me in a direction of how I can optimize my code to get more refreshes per second out of it? Purpose of this is for a small table-top Star Wars droid.

Thanks in advance for any help!

Source code backup: #include <SPI.h>#include <Wire.h>#include <Adafruit_GFX.h>#include <Adafru - Pastebin.com

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

int OLED_RESET = 4;
Adafruit_SSD1306 display(OLED_RESET);

void setup() {
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  delay(1000);
  display.clearDisplay();
  
  Serial.print("Display: ");
  Serial.print(display.width());
  Serial.print("x");
  Serial.println(display.height());
}

void loop() {
  drawRandomBitmap();
}

void  drawRandomBitmap() {
  for (int x = 0; x < display.width(); x++) {
    for (int y = 0; y < display.height(); y++) {
      display.drawPixel(x, y, ((rand() & 0x01) == 0) ? WHITE : BLACK);
    }
  }
  display.display();
  Serial.println("refreshed");
}

First off. You should use W, H arguments in the constructor.

You have chosen a convoluted way to create random pixels. i.e. 8192 calls to rand()
Note that your cut-price constructor expects 128x64 screen.

Since a 128x32 screen uses a 512 byte buffer, you could just call random() 512 times using a range of 0, 255 and store each 8-pixel byte directly in the buffer.

David.

david_prentice:
Since a 128x32 screen uses a 512 byte buffer, you could just call random() 512 times using a range of 0, 255 and store each 8-pixel byte directly in the buffer.

Thanks!

That sounds a lot more efficient.
I'm not sure how to populate the buffer directly, but your advice and a look at the documentation already brought me a lot closer, practically halved the execution time per frame.

Had to define the bitmap array in the utility function, because defining it at the top led to
"image_generator:11:35: error: array bound is not an integer constant before ']' token".
I want to keep it as flexible as possible, so I'm not hardcoding the width/height/buffer size.

const uint8_t  OLED_RESET = 4;
Adafruit_SSD1306 display(OLED_RESET);
const uint8_t  display_width = display.width();
const uint8_t  display_height = display.height();
const int display_buffer_size = (display_width * display_height) / 8;

and

void  drawRandomBitmap() {
  display.clearDisplay();
  for (int i = 0; i < display_buffer_size; i++) {
    bitmap[i] = random(0, 255);
  }
  display.drawBitmap (0, 0, bitmap, display_width, display_height, WHITE);

  display.display();
  Serial.println("refreshed");
}
Adafruit_SSD1306 display(128, 32, &Wire);  //use accurate constructor
...

void  drawRandomBitmap() 
{
    int display_buffer_size = (display.width() * display.height()) / 8;
    uint8_t *p = display.getBuffer();
    for (int i = 0; i < display_buffer_size; i++) {
        p[i] = random(0, 255); //write 8-pixels direct to buffer
    }
    display.display();   //sends the buffer to the OLED
    Serial.println("refreshed");
}

I guess that this will be at least 16x faster than your previous function.
Untested. I just typed into the Browser.

Thanks!

The constructor alone already halved it again (no idea why) and your function (which worked out of the box) then halved it once again.

Thanks to all of these steps this went from roughly 450 ms to around 60-70 ms and now the output looks like convincing static noise.

Couldn't have done it without your help!

If you want to change an image quickly, you can load the buffer directly.

For example, you can draw a screen with regular graphics e.g. drawBitmap()
Read the buffer, and write as a C array to Serial Terminal.

Copy the Serial Terminal to a tab in your sketch.
Subsequent programs can copy the PROGMEM array directly to the buffer.

This gives you fast animations.

David.

Thanks again!

In case anyone else comes across this thread looking for an Arduino static noise display, here's the resulting code:

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

const uint8_t  display_width = 128;
const uint8_t  display_height = 32;
const int display_buffer_size = (display_width * display_height) / 8;
Adafruit_SSD1306 display(display_width, display_height, &Wire);

void setup() {
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  delay(1000);
  display.clearDisplay();
}

void loop() {
  drawRandomBitmap();
}

void  drawRandomBitmap(){
    uint8_t *p = display.getBuffer();
    for (int i = 0; i < display_buffer_size; i++) {
        p[i] = random(0, 255); //write 8-pixels direct to buffer
    }
    display.display();   //sends the buffer to the OLED
}

This topic was automatically closed after 120 days. New replies are no longer allowed.