본문 바로가기

IoT

SSD1306 OLED

728x90



SSD1306 OLED


스펙

동작 전압 : 3v ~ 5V (제조사마다 차이)

통신 방식 : I2C or SPI

드라이버 IC : SSD1306

해상도 : 128 x 32 or 128 x 64



SSD1306 OLED 디스플레이

SSD1306 드라이버 IC를 사용하여 OLED 디스플레이를 제어하고 있으며

SSD1306의 경우는 128x32, 128x64등을 다양한 해상도를 지원하고 있으며 연결방식 또한 SPI(3,4-Wire)/I2C/8bit(8080,8060) 방식을 지원하고 있습니다

이번 게시물에 사용된 OLED는 128x32픽셀을 갖는 I2C인터페이스를 지원하는 하드웨어나 128 x 64픽셀의 SPI인터페이스의 하드웨어를 사용해볼수 있습니다



하드웨어 연결

일반적으로 기판상에 각 핀에 대한 설명이 보여집니다 (그렇지 않은 경우는 제조사 정보를 참조하여 주세요)

기본적으로 VCC는 MCU의 5v에  GND는 MCU의 GND에 연결하며

I2C의 경우는 

SCL과 SDA는 각각 MCU의 SDL과 SDA에 해당하는 아날로그 핀에 연결합니다 (아두이노 나노의 경우는 A4핀이 SDA이며 A5핀이 SCL핀이 됩니다)

SPI의 경우는

D0(SCK / SPI Clock), D1(MOSI / Serial DATA In),  RES/RST(Reset),  DC(Data Command),  CS(Chip Select)를 각각 MCU의 디지털 핀에 맵핑되어야 합니다 (아두이노 나노에서는 일단 임의로 RES->D8, DC->9, CS->10, D1->11, D0->13 으로 연결합니다)


I2C


SPI


(클릭하면 확대)



제어

기본적으로 I2C와 SPI 통신방식을 취하고 있기 때문에 SSD1306에 대한 제어를 위해서는 라이브러리 사용을 권장합니다

이미 SSD1306에서 활용가능한 다양한 라이브러리가 존재하며 기존에 u8glib가 많이 사용되었으며 최근에는 u8g2가 많이 사용되고 있는듯 합니다

u8g2 라이브러리의 경우 라이브러리 내에서 u8g2와 u8x8로 구분하여 사용되며 다음과 같은 차이점이 있습니다


u8g2 : 

다양한 그래픽 (라인, 박스, 원) 그리기가 포함됩니다

다양한 글꼴을 지원하며 글꼴의 높이 제한이 없습니다

디스플레이를 렌더링하기 위해 MCU의 메모리가 필요합니다

u8x8 :

텍스트 출력 전용

문자당 고정 크기로 허용되는 글꼴만 사용가능합니다

디스플레이에 직접쓰며 이로 인하여 MCU에 버퍼가 별도로 필요하지 않습니다


때문에 사용자가 필요로 하는 기능에 알맞게 활용하면 되며

각각의 라이브러리 Header 파일(U8g2lib.h, U8x8lib.h)을 참조하면 각 디바이스의 초기화에 필요한 셋업을 수행할 수 있습니다


u8g2 사이트 : https://github.com/olikraus/u8g2/wiki


참고로 이 게시물에서 사용된 SSD1306 드라이버 IC에 

128x32 픽셀 I2C OLED 하드웨어 경우 아래 함수를 사용하여 디바이스를 지정 및 핀 설정을 할 수 있습니다

u8g2 : U8G2_SSD1306_128X32_UNIVISION_2_SW_I2C u8g2();

u8x8 : U8X8_SSD1306_128X32_UNIVISION_SW_I2C u8x8();

128x64 픽셀 SPI OLED 하드웨어 경우는 아래 함수를 사용하여 디바이스를 지정 및 핀 설정을 할 수 있습니다

u8g2 : U8G2_SSD1306_128X64_NONAME_1_4W_SW_SPI u8g2();

u8x8 : U8X8_SSD1306_128X64_NONAME_4W_SW_SPI u8x8();



아두이노 지원 (ATmega328P)

다음 코드에서는 u8g2와 u8x8 두가지 방식을 #define U8X8TEST와 U8G2TEST로 구분하여 활성화 할 수 있도록 구성하였습니다

각각 #define 문을 주석처리에 따라 #ifdef 문에서 구분되어 실행됩니다

참고로 23, 33 번 라인의 주석은 128x64 SPI 인터페이스를 갖는 OLED 사용시 주석을 풀고 셋업에 사용할 수 있습니다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// 사용 라이브러리
// U8g2 by oliver 2.24.3
 
#include <Arduino.h>
#include <SPI.h>
 
// 핀 연결 (SPI)
// D0(CLK/SCK) :  13 
// D1(MOSI) :     11 
// RST(Reset) :   8 
// DC(DC/A0) :    9 
// CS(CS) :       10

// 핀 연결 (I2C)
// SCL : 5
// SDA : 4 
 
// u8g2 또는 u8x8 테스트 코드 선택
//#define U8X8TEST
#define U8G2TEST
 
///////////////////////////////////////////////////////////////////////////////
#ifdef U8X8TEST
// u8x8
#include <U8x8lib.h>
// 128x64 SPI OLED // (clock, data, cs, dc, reset)
//U8X8_SSD1306_128X64_NONAME_4W_SW_SPI u8x8(13, 11, 10, 9, 8); 
// 128x32 I2C OLED // (clock, data)
U8X8_SSD1306_128X32_UNIVISION_SW_I2C u8x8(54);
int inverse = 0// 글자 반전용 변수
#endif
///////////////////////////////////////////////////////////////////////////////
#ifdef U8G2TEST
// u8g2
#include <U8g2lib.h>
// 128x64 SPI OLED // (U8G2_R0, clock, data, cs, dc, reset)
//U8G2_SSD1306_128X64_NONAME_1_4W_SW_SPI u8g2(U8G2_R0, 13, 11, 10, 9, 8); 
// 128x32 I2C OLED // (clock, data)
U8G2_SSD1306_128X32_UNIVISION_2_SW_I2C u8g2(U8G2_R0, 54);
u8g2_uint_t display1_offset; //첫째라인 문장 위치
u8g2_uint_t display1_width; // 첫째라인 문장 길이
u8g2_uint_t display2_offset; // 둘째 라인 문장 위치
u8g2_uint_t display2_width; // 둘째 라인 문장 길이
char display_value1[48]="Hello  "//첫째라인 문장 내용
char display_value2[48]="Park  "// 둘째라인 문장 내용
#endif
///////////////////////////////////////////////////////////////////////////////
 
void setup()
{
  /////////////////////////////////////////////////////////////////////////////
#ifdef U8X8TEST
  // u8x8
  u8x8.begin(); // u8x8 초기화
#endif
  /////////////////////////////////////////////////////////////////////////////
#ifdef U8G2TEST
  // u8g2
  u8g2.begin(); // u8g2 초기화
  u8g2.setFont(u8g2_font_t0_15b_tf); // 문장 길이 계산을 위한 폰트 셋업
  display1_width = u8g2.getUTF8Width(display_value1); // 첫째라인 문장 길이 체크
  display2_width = u8g2.getUTF8Width(display_value2); // 둘째라인 문장 길이 체크
  u8g2.setFontMode(0); // 투명 모드 사용안함 (빠른 처리 가능)
#endif
  /////////////////////////////////////////////////////////////////////////////
}
 
void loop()
{
  /////////////////////////////////////////////////////////////////////////////
#ifdef U8X8TEST
  u8x8.clear(); // 화면을 모두 지우고 초기화
  u8x8.setFont(u8x8_font_chroma48medium8_r); // 폰트 설정
  // u8x8 폰트 리스트 : https://github.com/olikraus/u8g2/wiki/fntlist8x8
  
  // 글자 반전 주기
  if (inverse == 0) {
    u8x8.noInverse();
    inverse = 1;
  } else {
    u8x8.inverse();
    inverse = 0;
  }
 
  u8x8.setCursor(0,1); // 커서 위치 변경
 
  // 글자 그리기
  u8x8.draw1x2String(30"Bootup");
  u8x8.draw1x2String(32"Welcome");
  delay(3000);
#endif
  /////////////////////////////////////////////////////////////////////////////
#ifdef U8G2TEST
  //u8g2 // 좌측 스크롤
  u8g2_uint_t x_ssid;
  u8g2_uint_t x_ipaddress;
 
  // firstPage()와 nextPage()는 u8g2에서 디스플레이에 렌더링하기 위한 반복의 명령으로 사용
  u8g2.firstPage();
  do { // 현재 오프셋의 스크롤 텍스트를 그립니다
    x_ssid = display1_offset;
    u8g2.setFont(u8g2_font_t0_15b_tf); // 폰트 셋업
    // u8g2 폰트 리스트 : https://github.com/olikraus/u8g2/wiki/fntlistall
    
    // 첫째 문장 라인 그리기
    do { // 스크롤 텍스트를 의한 반복 그리기
      u8g2.drawUTF8(x_ssid, 12, display_value1); // 텍스트 그리기
      x_ssid += display1_width; // 스크롤 텍스트의 폭 픽셀을 더하기
    } while( x_ssid < u8g2.getDisplayWidth() ); // 첫라인 모두 체워질때까지 체우기
 
    x_ipaddress = display2_offset;
    u8g2.setFont(u8g2_font_t0_15b_tf);
 
    // 둘째 문장 라인 그리기
    do { // 스크롤 텍스트를 의한 반복 그리기
      u8g2.drawUTF8(x_ipaddress, 30, display_value2); // 텍스트 그리기
      x_ipaddress += display2_width; // 스크롤 텍스트의 폭 픽셀을 더하기
    } while( x_ipaddress < u8g2.getDisplayWidth() ); // 둘째라인 모두 체워질때까지 체우기
 
  } while ( u8g2.nextPage() );
 
  // 첫째 문장 스크롤 위치 변경
  display1_offset-=1// 한 픽셀씩 스크롤
  if ( (u8g2_uint_t)display1_offset < (u8g2_uint_t)-display1_width )
      display1_offset=0;
 
  // 둘째 문장 스크롤 위치 변경
  display2_offset-=1// 한 픽셀씩 스크롤
  if ( (u8g2_uint_t)display2_offset < (u8g2_uint_t)-display2_width )
      display2_offset=0;
#endif
  /////////////////////////////////////////////////////////////////////////////
}
 
cs


출력 결과

u8g2

  


u8x8

  




MBED 지원 (STmicroelectroics NUCLEO-L432KC)





SSD1306 Datasheet



728x90