준비물:
NodeMCU 개발보드 1개, OLED SSD1306 디스플레이 1개, micro-USB 케이블 1개, 브레스보드그림 1. 준비물 |
개발환경
아두이노 스케치 1.8.9
Wire 라이브러리 https://www.arduino.cc/en/reference/wire
ESP8266 OLED SSD1306 라이브러리 https://github.com/ThingPulse/esp8266-oled-ssd1306
I2C란
I2C 버스는 80년대 초반에 저속의 부품들을 연결하기 위한 목적으로 필립스에서 개발한 직렬버스이다. "Inter IC"라고도 하며, IIC, I2C 버스라고도 한다. I2C 통신은 다음과 같은 특징들을 갖는다.
- SDA, SCL 등 2개의 통신선만 사용하므로 구성이 간단하다.
- 마스터-슬레이브 관계로 연결하여 1:n 연결이 가능하다. 슬레이브는 고유의 주소로 구분한다.
- 통신 최대속도는 100Kbit/s이며, Fast mode(400Kbit/s), High speed mode(3.4Mbit/s)도 지원한다.
실습내용
아두이노의 경우 디폴트로 SDA와 SCL을 위해 GPIO4 핀과 GPIO5 핀이 지정되어 있지만, ESP8266의 경우 소프트웨어적인 방식으로 구현되어 있기 때문에 임의의 핀을 이용할 수 있다. 여기서는 D1(GPIO5), D2(GPIO4)핀을 SCL과 SDA로 지정했다. ESP8266은 마스터로 동작하며 OLED 디스플레이는 슬레이브로 동작한다.
Wire 라이브러리
ESP8266(마스터)에서 OLED 디스플레이(슬레이브)로의 데이터 전송은 먼저 버퍼를 준비하고, 버퍼에 데이터를 기록한 후 버퍼의 내용을 전달하는 3단계로 진행된다.
멤버 함수들을 사용하기 위해 우선 헤더 파일을 추가한다.
#include <Wire.h>
초기화
void begin(int sda, int scl)
- sda: SDA(Serial data) 핀 번호
- scl: SCL(Serial clock) 핀 번호
데이터 전송
슬레이브로의 데이터 전송은 beginTransmission 함수를 사용하여 전송을 위해 버퍼를 초기화하고, write 함수로 버퍼에 데이터를 기록한 후, endTransmission 함수로 버퍼에 기록된 데이터를 전송.
void beginTransmission(uint8_t address) void beginTransmission(int address)
- address: 슬레이브 주소
size_t write(uint8_t data) size_t write(const unint_8 *date, size_t quantity)
- data: 전송할 단일 바이트 또는 바이트 배열에 대한 포인터
- quantity: 전송할 바이트 수
- RETURN: 전송된 바이트 수
uint8_t endTransmission(void) uint8_t endTransmission(uint8_t sendStop)
- sendStop: 요청 완료 후 정지 메시지 전송 여부 (false: 전송 완료 후 연결 유지. 다른 마스터 장치가 데이터 전송 불가능. 디폴트 true.)
- RETURN: 전송 상태 메시지 (성공시 0 리턴. 오류 값 리턴)
마스터(ESP8266)가 requsestFrom 함수를 이용하여 특정 주소의 슬레이브에게 지정된 바이트 수만큼 데이터를 요청한 뒤 데이터 수신을 대기한다. 수신 여부는 available 함수를 통해 확인한다.
데이터 수신
uint8_t requestFrom(uint8_t address, uint8_t quantity) uint8_t requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop)
- address: 슬레이브 주소
- quantity: 요청 바이트 수
- sendStop: 요청 완료 후 정지 메시지 전송(true, false 전송 유지)
- RETURN: 슬레이브 장치로부터 전송된 바이트 수
int available(void)
- RETURN: 버퍼 내 수신된 데이터 바이트 수
int read(void)
- RETURN: 수신 버퍼의 한 바이틀 읽어서 반환
ESP8266 OLED SSD1306 라이브러리
헤더 파일 추가 및 초기화
#include "SSD1306Wire.h" SSD1306Wire DISPLAY(0x3c, D3, D5); // NodeMCU D3 핀과 D5핀을 SDA와 SCL로 설정 // SSD1306Wire DISPLAY(0x3c, SDA, SCL); // ADDRESS, SDA, SCL
디스플레이 제어
// 디스플레이 초기화 void init(); // 디스플레이가 사용하는 메모리를 비움 void end(); // 초기화 반복 void resetDisplay(void); // I2C를 이용하여 디스플레이에 다시 연결 void reconnect(void); // 디스플레이 켜기 void displayOn(void); // 디스플레이 끄기 void displayOff(void); // 버퍼를 디스플레이 메모리에 기록 (디스플레이에 출력됨) void display(void); // 디스플레이 반전 시킴 void invertDisplay(void); // 디스플레이 반전 해제 void normalDisplay(void); // 디스플레이 콘트라스트 조정 void setContrast(uint8_t contrast, uint8_t precharge = 241, uint_8_t comdetect = 64); // 디스플레이 상하 뒤집기 void flipScreenVertically();
픽셀 그리기
// 색상 지정 (컬러 지원 OLED의 경우) void setColor(OLEDDISPLAY_COLOR color); // 좌표 값에 픽셀 그리기 void setPixel(int16_t x, int16_t y); // 두 좌표 값으로 선 그리기 void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1); // 좌표를 기준으로 사각형 그리기 void drawRect(int16_t x, int16_t y, int16_t width, int16_t height); // 좌표를 기준으로 채워진 사각형 그리기 void fillRect(int16_t x, int16_t y, int16_t width, int16_t height); // 원그리기 void drawCircle(int16_t x, int16_t y, int16_t radius); // 채워진 원그리기 void fillCircle(int16_t x, int16_t y, int16_t radius); // 가로선 그리기 void drawHorizontalLine(int16_t x, int16_t y, int16_t length); // 세로선 그리기 void drawVerticalLine(int16_t x, int16_t y, int16_t length); // 진행바 그리기 (progress 값 0 ~ 100) void drawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint_t progress); // 이미지 비트맵 그리기 void drawFastImage(int16_t x, int16_t y, int16_t width, int16_t height, const uint8_t *image); // XBM 그리기 void drawXBM(int16_t x, int16_t y, int16_t width, int16_t height, const char *xbm);
텍스트 명령
void drawString(int16_t x, int16_t y, String text); // 정해진 폭 범위 내에 최대한 표시. 주어진 폭 길이보다 넓게 글을 표시할 경우 공백이나 '-' 표시후 개행 void drawStringMaxWidth(int16_t x, int16_t y, int16_t maxLineWidth, String text); uint16_t getStringWidth(const char* text, uint16_t length); uint16_t getStringWidth(String text); // 정렬 void setTextAlignment(OLEDDISPLAY_TEXT_ALIGNMENT textAlignment); // 폰트 설정 // ArialMT_Plain_10, ArialMT_Plain_16, ArialMT_Plain_24 void setFont(const uint8_t* fontData);
UI 라이브러리 (OLEDDisplayUi)
Ui 라이브러리는 Frame과 Overay라고 하는 기본적인 UI 요소들의 집합으로 구성되어 있다. Frame은 움직이는 화면을 Overay는 정지된 화면을 제어한다.
// 초기화 void init(); // 초당 프레임 수 지정 void setTargetFPS(uint_t fps); // 프레임 자동 전환 void enableAutoTransition(); void disableAutoTransition(); // 자동 전환 설정시 전환 방향 지정 void setAutoTransitionForwards(); void setAutoTransitionBackwards(); // 시간당 표시 프레임 void setTimePerFrame(uint16_t time); // 전환 시간 void setTimePerTransition(uint16_t time); void enalbeIndicator(); void disableIndicator(); void enableAllIndicators(); void disableAllIndicators(); void setIndicatorPosition(IndicatorPosition pos); void setIndicatorDirection(IndicatorDirection dir); void setActiveSymbol(const char* symbol); void setInactiveSymbol(const char* symbol); void setFrameAnimation(AnimationDirection dir); void setFrames(FrameCallback* frameFunctions, uint8_t frameCount); void setOverlays(OverlayCallback* overlayFunctions, uint8_t overlayCount); void setLoadingDrawFunction(LoadingDrawFunction loadingDrawFunction); void runLoadingProcess(LoadingStage* stages, uint8_t stagesCount); void nextFrame(); void previousFrame(); void switchToFrame(uint8_t frame); void transitionToFrame(uint8_t frame); OLEDDisplayUiState* getUiState(); int8_t update();
댓글
댓글 쓰기