I2C OLED 모듈
개요
아두이노 OLED 모듈은 작은 크기와 높은 해상도를 가진 디스플레이 모듈로, 다양한 프로젝트에 활용될 수 있습니다. OLED(Organic Light Emitting Diode) 기술을 기반으로 하여, 뛰어난 색감과 명암비를 제공합니다.
OLED 작동 원리
- 유기 물질: OLED는 얇은 유기 물질 층을 포함하고 있으며, 이 층이 전류에 의해 빛을 발산합니다. 유기 화합물은 전기적 자극을 받을 때 발광하는 특성을 가지고 있습니다.
- 전극: OLED 패널은 일반적으로 두 개의 전극(양극과 음극)으로 구성되어 있으며, 전기가 흐르면 유기 물질이 전자를 방출하고, 이 전자와 정공이 결합하여 빛을 생성합니다.
SSD1306
SSD1306은 OLED 디스플레이를 구동하기 위한 드라이버 IC(집적 회로)입니다.
1KB의 그래픽 디스플레이 전용 RAM(GDDRAM)을 내장하고 있어 이를 통해 표시할 비트 패턴을 저장합니다.
항목 | 설명 |
---|---|
메모리 용량 | 1KB (8192비트) |
페이지 수 | 8 페이지 (페이지 0-7) |
세로 줄 수 | 128 세로 줄 (세로 줄 0-127) |
비트 정보 | 각 세로 줄당 8 비트 (비트 0-7) |
계산 | 8 페이지 x 128 세로 줄 x 8 비트 = 8192 비트 = 1024 바이트(1KB) |
사양
항목 | 설명 |
---|---|
화면 크기 | 0.91인치, 0.96인치, 1.3인치 등 다양한 크기 |
해상도 | 128x64 픽셀 또는 128x32픽셀 |
디스플레이 타입 | OLED (Organic Light Emitting Diode) |
색상 | 흑백 (화이트 또는 블루) |
인터페이스 | I2C (2선) |
전압 | 3.3V ~ 5V |
전력 소모 | 대기 전력: 약 0.1mA, 최대 전력: 약 20mA |
활용 예제
회로 구성
OLED 모듈 핀 | 아두이노 우노/나노 | 아두이노 메가 |
---|---|---|
VCC | 5V 또는 3.3V | 5V 또는 3.3V |
GND | GND | GND |
SCL | A5 | 21 |
SDA | A4 | 22 |
장치 주소 확인
I2C 버스에 연결된 장치의 주소를 찾기 위해 사용되는 코드입니다.
아래 소개될 예제들을 실행하기 이전에 I2C Scanner를 먼저 실행해 모듈의 주소를 확인해주세요.
#include <Wire.h>
void setup() {
Serial.begin(9600); // 시리얼 통신 시작
Wire.begin(); // I2C 버스 시작
Serial.println("I2C Scanner 시작...");
}
void loop() {
byte error, address;
int nDevices = 0;
Serial.println("I2C 장치 검색 중...");
for (address = 1; address < 127; address++) {
// I2C 장치에 연결 시도
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
Serial.print("장치 발견! 주소: 0x");
if (address < 16) {
Serial.print("0");
}
Serial.print(address, HEX);
Serial.println();
nDevices++;
} else if (error == 4) {
Serial.print("주소 0x");
Serial.print(address, HEX);
Serial.println("에 오류 발생!");
}
}
if (nDevices == 0) {
Serial.println("I2C 장치가 발견되지 않았습니다.");
} else {
Serial.println("장치 검색 완료.");
}
delay(5000); // 5초 대기 후 다시 스캔
}
실행 결과
라이브러리
Adafruit SSD1306 라이브러리를 사용합니다.
SSD1306 설치시 추가로 요구하는 Adafruit BusIO, Adafruit GFX Library도 INSTALL ALL을 눌러 함께 설치해주세요.
1. 라이브러리 기본 제공 예제
File - Examples - Adafruit SSD1306 - ssd1306_128x64 i2c 를 클릭하여 예제를 열어주세요.
예제 코드 속 Address 부분을 이전에 I2C Scanner로 확인한 장치 주소로 변경해주세요.
실행 결과
2. 텍스트 출력
간단한 텍스트를 출력하는 예제입니다.
0.91인치 OLED를 사용했으며 이 모듈의 경우 128 x 32픽셀이기 때문에 6번째 줄 SCREEN_HEIGHT를 64에서 32로 변경했습니다.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED 화면의 너비
#define SCREEN_HEIGHT 32 // OLED 화면의 높이
// OLED 모듈의 I2C 주소 (일반적으로 0x3D 또는 0x3C)
#define OLED_ADDR 0x3C
// Adafruit_SSD1306 객체 생성
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void setup() {
// OLED 초기화
display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
display.clearDisplay(); // 화면 지우기
display.setTextSize(1); // 텍스트 크기 설정
display.setTextColor(SSD1306_WHITE); // 텍스트 색상 설정
display.setCursor(0, 0); // 커서 위치 설정
display.println("GONGZIPSA"); // 텍스트 출력
display.setCursor(0, 10); // 커서 위치 설정
display.println("ArduWiki"); // 텍스트 출력
display.display(); // 화면에 출력
}
void loop() {
// 루프에서는 아무 작업도 하지 않음
}
사용된 함수들의 역할은 다음과 같습니다.
함수 이름 | 설명 |
---|---|
begin()
|
OLED 디스플레이를 초기화합니다. I2C 주소와 해상도를 설정합니다. |
clearDisplay()
|
현재 디스플레이의 내용을 지웁니다. 화면을 초기화합니다. |
setTextSize(size)
|
출력할 텍스트의 크기를 설정합니다. size 는 배율을 나타냅니다. (예: 1, 2 등)
|
setTextColor(color)
|
텍스트의 색상을 설정합니다. 일반적으로 SSD1306_WHITE , SSD1306_BLACK 를 사용합니다.
|
setCursor(x, y)
|
텍스트를 출력할 위치를 설정합니다. x 는 가로 위치, y 는 세로 위치입니다.
(0, 0)이 왼쪽 상단이며 |
println("출력 내용") | 출력할 내용을 설정합니다. |
display()
|
버퍼에 저장된 내용을 OLED 디스플레이에 출력합니다. |
실행 결과
3. 간단한 도형 출력
사각형, 삼각형, 원 등 간단한 도형들을 출력하는 예제입니다.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_ADDR 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
display.clearDisplay(); // 화면 초기화
display.drawTriangle(10, 10, 40, 30, 10, 30, WHITE); // 작은 삼각형
display.drawRect(50, 10, 30, 20, WHITE); // 사각형
display.fillRect(90, 10, 30, 20, WHITE); // 채워진사각형
display.drawCircle(25, 50, 13, WHITE); // 원
display.drawRoundRect(50, 40, 30, 20, 7, WHITE); // 모서리가 둥근 사각형
display.fillRoundRect(90, 40, 30, 20, 7, WHITE); // 모서리가 둥근 채워진 사각형
display.display();
}
void loop() {
}
도형과 관련된 함수들은 다음과 같습니다.
함수 이름 | 설명 |
---|---|
drawLine(x1, y1, x2, y2, color)
|
두 점을 연결하는 선을 그립니다. |
drawRect(x, y, width, height, color)
|
빈 사각형을 그립니다. |
fillRect(x, y, width, height, color)
|
채워진 사각형을 그립니다. |
drawCircle(x, y, radius, color)
|
빈 원을 그립니다. |
fillCircle(x, y, radius, color)
|
채워진 원을 그립니다. |
drawTriangle(x1, y1, x2, y2, x3, y3, color)
|
삼각형을 그립니다. |
drawRoundRect(x, y, width, height, radius, color)
|
둥근 모서리가 있는 사각형을 그립니다. |
fillRoundRect(x, y, width, height, radius, color)
|
채워진 둥근 모서리 사각형을 그립니다. |
실행결과
4. 아스키 코드 출력
아스키 코드 표에 대응하는 1~8번 문자를 출력하는 예제입니다.
더 많은 문자를 출력하시려면 아스키 코드 표를 참고하세요.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_ADDR 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
display.clearDisplay(); // 화면 초기화
// 텍스트 출력 설정
display.setTextSize(1); // 텍스트 크기 설정
display.setTextColor(WHITE); // 텍스트 색상 설정
display.setCursor(0, 0); // 커서 위치 설정
// 아스키 코드 문자 출력
display.println("ASCII Code Print");
// 아스키 코드 문자 출력
for (char c = 1; c < 9; c++) { // 아스키 코드 1부터 8까지
display.print(c); // 각 문자 출력
display.print(" "); // 공백 추가
}
display.display(); // 버퍼 내용을 화면에 출력
}
void loop() {
// 반복할 작업이 없으므로 빈 상태
}
실행 결과
5. 비트맵 이미지 출력
이미지를 바이트 배열로 변환하여 OLED에서 출력하는 예제입니다.
이미지를 바이트 배열로 변환하는 방법
1. image2cpp (javl.github.io) 로 접속합니다.
2. 이미지 업로드
좌측 Select image에서 파일을 선택하여 업로드합니다.
3. 이미지 세팅
Canvas size에 이미지 사이즈를 입력하신 후, Preview를 확인합니다. 이미지가 너무 큰데 Canvas 이미지를 작게 만드는 등 사이즈 조절이 잘 못 된다면 Preview에 정상적으로 이미지가 출력되지 않습니다.
4. 출력
Code output format을 Arduino Code로 설정하신 후 Generate code를 누르면 아래에 배열이 출력됩니다.
출력된 배열을 복사하여 예제 코드에서 활용하세요.
예제 코드
drawBitmap(x, y, bitmap, width, height, color)
함수를 사용하여 지정된 위치에 비트맵 이미지를 그립니다.
color
는 흰색으로 설정되어 있어 이미지를 흰색으로 표시합니다.
12번째 줄 const unsigned char ~ 부분을 위에서 만든 바이트 배열로 변경하여 활용하세요.
예제 이미지(64 x 64 사이즈)와 사이즈가 다르다면 56번째 줄 drawBitmap 함수의 x, y 커서 위치, width, height 사진 크기를 변경해주셔야 합니다.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_ADDR 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// GONGZIPSA LOGO
const unsigned char GONGZIPSA [] PROGMEM = {
0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xf0, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x03, 0xff, 0xff,
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff,
0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff,
0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0x80, 0x00, 0x10, 0x00, 0x40, 0x01, 0xff,
0xff, 0x00, 0x00, 0x30, 0x00, 0xe0, 0x00, 0xff, 0xff, 0x00, 0x00, 0x70, 0x00, 0xf0, 0x00, 0xff,
0xfe, 0x00, 0x00, 0xf0, 0x00, 0xf8, 0x00, 0x7f, 0xfc, 0x00, 0x01, 0xf0, 0x00, 0xfc, 0x00, 0x3f,
0xf8, 0x00, 0x03, 0xf0, 0x00, 0xfc, 0x00, 0x1f, 0xf8, 0x00, 0x03, 0xf0, 0x00, 0xff, 0x00, 0x1f,
0xf0, 0x00, 0x07, 0xf0, 0x00, 0xff, 0xe0, 0x07, 0xff, 0x80, 0x3e, 0xf0, 0x01, 0xff, 0xf8, 0x7f,
0xbf, 0xf1, 0xff, 0xe0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xf7,
0xdf, 0xff, 0xff, 0xf0, 0x0f, 0xef, 0xff, 0xf3, 0xc7, 0xdf, 0xff, 0xf0, 0x0f, 0xe7, 0xff, 0x63,
0xc3, 0xff, 0xfc, 0xb0, 0x0f, 0xef, 0xff, 0xe3, 0x81, 0xff, 0xf9, 0xb0, 0x0f, 0xff, 0xff, 0xc1,
0x80, 0xff, 0xf1, 0x70, 0x07, 0xff, 0xcd, 0xc1, 0x80, 0xf9, 0xfc, 0xf0, 0x0f, 0xff, 0xef, 0xc1,
0x80, 0xc9, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xe1, 0x80, 0x5c, 0xff, 0xe0, 0x07, 0xfb, 0xff, 0xc1,
0x00, 0x7f, 0xcf, 0xe0, 0x07, 0xfb, 0xff, 0xc0, 0x00, 0x3f, 0xcf, 0xc0, 0x03, 0xff, 0xff, 0x80,
0x00, 0x1f, 0xff, 0x80, 0x01, 0xff, 0xff, 0x80, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x7f, 0xff, 0x00,
0x00, 0x07, 0xff, 0x80, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x01, 0xff, 0x80, 0x00, 0xff, 0xf4, 0x00,
0x00, 0x00, 0x7f, 0xc0, 0x01, 0xff, 0x90, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x03, 0xff, 0x80, 0x00,
0x80, 0x00, 0xff, 0xe0, 0x03, 0xff, 0x80, 0x01, 0x80, 0x00, 0x73, 0x30, 0x02, 0x07, 0x00, 0x01,
0x80, 0x71, 0xcb, 0x4e, 0x7d, 0x78, 0xf0, 0x81, 0x81, 0xf3, 0xec, 0xdf, 0x7f, 0xfd, 0xf1, 0x81,
0x81, 0x06, 0x2c, 0xf0, 0x0b, 0xc7, 0x01, 0x81, 0xc1, 0x04, 0x7c, 0xe0, 0x13, 0xcf, 0x83, 0x83,
0xc3, 0x3c, 0x7a, 0xe6, 0x23, 0xf9, 0xf2, 0xc3, 0xc3, 0x1c, 0x73, 0xe2, 0x63, 0x80, 0x16, 0xc3,
0xe3, 0x1c, 0x53, 0xe2, 0xc3, 0x80, 0x17, 0xc7, 0xe3, 0xf7, 0xd1, 0xff, 0xf7, 0x83, 0xfc, 0xc7,
0xf1, 0xe3, 0x91, 0x3f, 0xff, 0x03, 0xc8, 0x4f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0f,
0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff,
0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff,
0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
0xff, 0xff, 0xc0, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x0f, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff
};
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
display.clearDisplay(); // 화면 초기화
}
void loop() {
display.clearDisplay(); // 화면 지우기
// 64x64 비트맵 이미지 그리기
display.drawBitmap(32, 0, GONGZIPSA, 64, 64, WHITE); // (x, y, bitmap, width, height, color)
display.display(); // 버퍼 내용을 화면에 출력
}
실행 결과
플리커링 현상 때문에 모습 촬영 시에 잘려서 보이지만 실제로는 동그란 로고가 깔끔하게 출력되었습니다.