TIM Labs

Arduinoではオブジェクトの使い回しでメモリ不足を回避

128×64ドットで、多数jの文字を表示するのは、1画面ならOKだが、2画面だとダメだった。

ということで、次のような実験をした。

  1. 画面を128×64ではなく、128x32を指定してみた。
  2. 表示する文字数をぐっと半分以下に減らしてみた。

これだと、ディスプレイの上半分だけが使われるのだろうか。

プログラム全体を以下に示す。

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define OLED_RESET     4

Adafruit_SSD1306 display1(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_SSD1306 display2(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void setup() {
  Serial.begin(115200);
  display1.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display2.begin(SSD1306_SWITCHCAPVCC, 0x3D);

  displayText(display1, "Arduino is an open-source hardware and software company,"
                        "project and user community ");
                       
  displayText(display2, "that designs and manufactures "
                        "single-board microcontrollers and microcontroller kits " );
} 

void loop() {
  
}

void displayText(Adafruit_SSD1306 disp, char* text) {
  disp.setTextColor(WHITE);
  disp.clearDisplay();
  disp.setTextSize(1);
  disp.setCursor(0,0);
  disp.print(text);
  disp.display();
}

すると、結果はこうなった。

OLED-128x32displa2.JPG

文字が縦に倍に伸ばされているようだ。1行の文字数には変化がない。

さて、どうして、128×64では動かず、128×32にしたら動いたのであろうか。

たぶん、以下のような理由ではないかと思う。

画面が128x64ドットということは、128×64 = 8192画素なので、モノクロ画面イメージを保持するには8192ビット、つまり1KBのメモリが必要になる。

すると、次の2行で、

Adafruit_SSD1306 display1(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
Adafruit_SSD1306 display2(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

2つのオブジェクトが作られ、各オブジェクトには画面イメージ1024バイト必要で、オブジェクトにはその他の値も少しは保持されるので、1オブジェクトが1KBよりやや大きいはずである。

ところで、Arduinoのメインメモリ(SRAM)は2048バイトしかない。

一部の特殊なものは多数のメモリを搭載している。例えば、Arduino Zeroは32ビットCPUのArmが載っていて、SRAM 32KBとなっている。Zeroがついていると、性能が落ちると思い込んではいけない。

ということは、それぞれの画面毎にオブジェクトを作ったら、それだけでメモリが足りなくなるので、動作しないのは当然だ。

それでも、それぞれの画面に、小さい字で8行表示したいと思い、次のように変更した。

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     4

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

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

  displayText(0x3C,"Arduino is an open-source hardware and software company,"
                       "project and user community that designs and manufactures "
                       "single-board microcontrollers and microcontroller kits " );
  displayText(0X3D,"for building digital devices and interactive objects "
                       "that can sense and control both physically and digitally.");
} 

void loop() {
  exit(0);
}

void displayText( int addr, char* text) {
  display.begin(SSD1306_SWITCHCAPVCC, addr );
  display.setTextColor(WHITE);
  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(0,0);
  display.print(text);
  display.display();
}

そして結果は、めでたくこうなった。

DSCN4799-400.JPG

要するに、オブジェクトは1つ作るだけで、displayText関数には、I2Cのアドレスと文字列を渡すことにした。

そして、displayText()では、最初に渡されたI2Cアドレスを指定して初期化してから表示処理をするようにした。

蛇足だが、このOLEDでは、送られてきた画面データはずっと保持されているので、最初のOLEDは放置して、次のOLEDの処理を行うことができる。

これを上手く使えば、多数のOLEDの表示を、1つのArduinoで制御できる。

OLEDの話が予定より長くなってしまった。次からは、別の話題にする。

このブログ記事について

このページは、fujiが2019年7月29日 00:00に書いたブログ記事です。

ひとつ前のブログ記事は「128x64ドットのOLEDに、8行21文字、全168文字を表示」です。

次のブログ記事は「Arduinoで作る簡易オシロスコープが400円でできた」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

月別 アーカイブ