앞선 글에서는 ESP32 개발보드를 PlatformIO 개발환경에서 사용하는데 필요한 준비 작업을 알아보았습니다. 이번은 그 마지막으로 간단한 프로그램을 만들어 ESP32 개발보드에서 실행시키고 모니터링하는 방법을 정리헤보겠습니다. 프로그램은 두 가지로 첫번째는 화면에 데이터를 출력하는 방법을, 두번째는 사용자로부터 입력을 받는 방법을 다룹니다. 데이터의 입출력은 개발의 기본인만큼 앞으로 수도 없이 사용하게 될 것입니다. 예제를 모두 따라하시면 이제
Table of Contents
1. Hello, World 프로그램 작성
1.1. 소스 코드 작성
기존 글에서 생성했던 프로젝트를 불러오면 그림 1과 같이 src 폴더에 자동으로 생성된 main.cpp 파일이 있습니다. main.cpp 파일을 열면 기본으로 제공되는 예제 코드가 있습니다만 불필요하므로 삭제해줍니다.

예제 코드를 지운 다음 아래와 같이 Hello, World 프로그램을 작성해주시기 바랍니다. 이번 프로그램은 시리얼 모니터에 “Hello, World”를 출력한 다음 사용자의 이름을 묻습니다. 사용자가 이름을 입력하면 반갑다고 인사를 합니다.
#include <HardwareSerial.h> // 시리얼 포트 클래스
#include <WString.h> // Arduino String 클래스
void setup()
{
Serial.begin(115200);
Serial.println("Hello, World!");
Serial.println("What is your name?");
}
void loop()
{
if (Serial.available() > 0)
{
const String name = Serial.readString();
Serial.printf("Nice to meet you, %s", name);
}
}
1.2. 소스 코드 설명
1번부터 2번 줄까지는 Arduino 프레임워크의 빌트인 라이브러리를 참조하는 내용입니다. 순서대로 시리얼 포트 클래스와 String 클래스가 선언되어 있습니다. 전자는 시리얼 모니터에 데이터를 출력하거나 사용자의 입력을 받는 데 사용됩니다. String 클래스는 사용자의 이름을 저장하는 데 사용됩니다. String 클래스는 문자를 쉽게 다룰 수 있도록 도와줄 뿐만 아니라 C++ 표준의 std::string 클래스 대비 가벼워 컴퓨팅 자원이 한정된 임베디드 환경에 적합합니다.
#include <HardwareSerial.h> // 시리얼 포트 클래스
#include <WString.h> // Arduino String 클래스
4번-10번 줄은 셋업 함수로 Arduino 프로그램에서 단 한 번만 실행되는 초기 설정 함수입니다. 일반적으로 GPIO 같은 핀(pin)이나 시리얼 포트 설정 작업을 수행합니다. 여기서는 시리얼 포트를 열어준 다음 시리얼 모니터로 문자열을 출력함으로써 초기 설정을 종료하도록 하겠습니다.
6번 줄에서는 HardwareSerial::begin(unsigned long baud, ...)
함수를 호출해 시리얼 포트를 열어줍니다. 이때 통신 속도는 115,200bps 로 설정했는데 시리얼 모니터의 통신 속도와 동일하게 맞춰야 합니다. 그렇지 않으면 데이터가 정상적으로 처리되지 못하기 때문입니다. Serial
개체는 HardwareSerial
클래스의 인스턴스로 시리얼 포트를 사용하는데 필요한 기능을 제공합니다.
다음으로 8번-9번 줄에서는 Print::println(const String &s)
함수를 사용해 “Hello, World”와 “What is your name?” 문자열을 시리얼 모니터로 출력합니다. Print
클래스는 Arduino에서 텍스트 출력에 필요한 일반적인 기능을 제공하는 상위 클래스입니다. 그래서 HardwareSerial
클래스 또한 Print
클래스를 상속받도록 설계되어 있고, 그로 인해 부모 클래스의 기능 중 하나인 println(const String &s)
함수를 호출할 수 있습니다.
void setup()
{
Serial.begin(115200);
Serial.println("Hello, World!");
Serial.println("What is your name?");
}
12번-19번 줄은 루프 함수로 void setup()
함수가 종료된 이후 Arduino 프로그램 내에서 무한히 반복되는 함수입니다. 일반적으로 프로그램이 실행해야 하는 핵심적인 기능들을 작성합니다. 여기서는 사용자가 이름을 입력하면 인사 문구를 시리얼 모니터에 출력합니다. 예를 들어, 제 필명인 Mirinae
를 입력하면 Nice to meet you, Mirinae
라는 문자열이 시리얼 모니터에 출력됩니다.
14번 줄은 사용자로부터의 입력이 있는지를 확인합니다. HardwareSerial::available()
함수는 시리얼 포트의 입력 버퍼에 쌓인 바이트의 개수를 반환합니다. 따라서 available()
함수의 반환값이 0보다 크다면 입력을 받았다는 뜻이기 때문에 16번-17번 줄을 실행합니다. 그렇지 않다면 다시 루프를 돌면서 사용자의 입력이 있는지 확인합니다.
16번 줄은 사용자가 입력한 데이터를 String name
개체에 저장합니다. 이때 HardwareSerial
클래스의 부모 클래스의 함수인 Stream::readString()
를 사용합니다. readString()
함수는 입력 버퍼에 쌓인 데이터를 String
개체로 반환합니다. 참고로 Stream
클래스는 앞서 살펴본 Print
클래스의 자식 클래스입니다. 맨 앞에 붙은 const
키워드는 name
개체에 저장된 값을 바꾸지 말라는 프로그래머의 의도를 나타내는 역할을 합니다.
17번 줄에서는 Print::printf(const char *format, ...)
함수를 사용해 서식 문자열(format string)을 시리얼 모니터에 출력하는 함수입니다. 이때 문자열을 의미하는 서식 지정자(format specifier) %s
위치는 name 변수의 값으로 대체됩니다. Print::print()
또는 Print::
함수만 사용하면 코드가 여러 줄로 늘어나는 반면에 println
()Print::printf
함수를 사용하면 한 줄의 코드로 끝날 수 있기 때문에 보다 복잡한 출력이 필요할 때 유용합니다.
void loop()
{
if (Serial.available() > 0)
{
const String name = Serial.readString();
Serial.printf("Nice to meet you, %s", name);
}
}
2. 프로그램 빌드 및 업로드
PlatformIO IDE에서 프로그램을 빌드하는 방법은 두 가지가 있습니다. 하나는 왼쪽의 사이드바
, 다른 하나는 상태 표시줄
을 사용하는 방법입니다. 사이드바는 VS Code 왼쪽에 위치한 아이콘들의 모음입니다. 상태 표시줄은 VS Code 하단에 프로젝트 상태, 오류 및 경고 등의 숫자 정보를 표시합니다. 전자는 숫자로, 후자는 알파벳 대문자로 표시했습니다.
2.1. 프로그램 빌드
그림 2와 같이 1번 아이콘을 클릭하면 사이드바가 열리고 프로젝트와 관련된 작업들의 목록이 표시됩니다. 여기서 Default
와 esp32dev
는 PlatformIO 작업 환경을 의미합니다. 지금은 하나의 작업 환경만 있기 때문에 Default
와 esp32dev
는 동일합니다. 하지만 서로 다른 작업 환경이 설정된 경우에는 빌드하고자 하는 작업 환경을 선택해야 합니다. 상태 표시줄에서도 작업 환경을 확인할 수 있습니다. 상태 표시줄의 Default (Hello World)
아이콘이 현재 설정된 작업 환경입니다. Default (Hello World)
아이콘을 클릭하면 다른 작업 환경을 선택할 수 있습니다.

2.2. 프로그램 업로드
빌드가 끝났다면 2번 아이콘 또는 A 아이콘을 클릭하여 프로그램을 ESP32 개발보드로 업로드합니다. 프로그램 업로드 속도는 작업 환경의 설정에 따라 달라집니다. 자세한 내용은 프로그램 업로드 설정 방법을 참조해주세요.

3. 프로그램 모니터링
3.1. 시리얼 모니터: 데이터 수신
모니터링 시에는 작업 환경에서 설정한 monitor_speed
속성의 값과
함수의 HardwareSerial::begin(unsigned long baud, ...)
매개변수의 값이 일치해야 합니다. 그렇지 않으면 송수신 되는 데이터가 유실됩니다. 자세한 내용은 프로그램 모니터 설정 방법을 참조해주세요.unsigned long baud

3.2. 프로그램 빌드, 업로드 및 모니터링
프로그램 빌드, 업로드, 모니터링 버튼을 매번 순서대로 클릭하기는 불편합니다. 다행히 PlatformIO에서는 Upload and Monitor
버튼만 한번 클릭하면 이러한 과정을 알아서 진행해줍니다. 다만 Upload and Monitor
버튼은 아쉽게도 상태 표시줄에 제공되지 않습니다.

그림 6은 Upload and Monitor
버튼을 클릭했을 때의 화면으로 프로그램 빌드 및 업로드 이후 자동으로 시리얼 모니터가 열린 상태입니다. 노랑색 음영 부분은 앞서 작성한 코드의 08
–09
번 줄의 문자열이 시리얼 모니터에 정상적으로 출력된 것을 확인할 수 있습니다.

3.3. 시리얼 모니터: 데이터 송신
여기서 사용자의 이름을 입력해줍니다. 저는 블로그에서 사용 중인 이름인 mirinae
를 입력했습니다. 그림 7의 빨강색 음영으로 표시된 부분에 입력한 데이터가 보입니다. 입력한 데이터를 ESP32로 전송하려면 엔터 키를 눌러줘야 합니다. 엔터 키를 누르면 ESP32가 응답(노랑색 음영)을 해주는 것이 보입니다.

빨강색 음영에 사용자의 입력 데이터를 표시하려면 작업 환경에서 monitor_echo 속성의 값을 true로 설정해줘야 합니다. 다음은 이번 프로젝트에 사용한 작업 환경의 설정입니다. 작업 환경 설정은 platformio.ini
파일에 작성합니다.
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
; Upload options
upload_port = COM101 ; serial port for program upload
upload_speed = 921600 ; set it slower if you have problems
upload_protocol = esptool ; default protocol for ESP32
; Monitor options
monitor_port = COM101 ; serial port for program monitor
monitor_speed = 115200 ; set it below slower if you have problems
monitor_echo = true ; display user input in the serial monitor
monitor_filters =
log2file ; automatically save log message to a file
send_on_enter ; send user input when enter is pressed
esp32_exception_decoder ; decodes ESP32 call stacks when it crashes
3.4. 저장된 로그 데이터 확인
시리얼 모니터로 수신한 데이터는 로그 파일로 저장시킬 수 있습니다. 이는 향후 디버깅이나 프로그램 동작 분석과 같은 작업에 유용합니다. 작업 환경의 monitor_filters
속성으로 send_on_enter
필터를 사용하면 시리얼 모니터가 열릴 때마다 자동으로 로그 파일에 시리얼 모니터로 수신한 데이터를 저장합니다. send_on_enter
필터 적용 시 로그 파일은 프로젝트 내부의 logs
폴더에 저장됩니다. 해당 폴더는 자동으로 생성됩니다. 로그 파일의 이름은 시리얼 모니터가 열린 시점을 기준으로 하여 자동으로 생성됩니다.
다만 사용자의 입력은 시리얼 모니터와 달리 로그 파일에 저장되지 않는다는 점에 주의해야 합니다. 그림 8의 노랑색 음영을 보면 그림 7의 빨강색 음영과 달리 사용자의 입력에 대한 내용이 저장되지 않았다는 것을 알 수 있습니다. 만약 사용자의 입력 데이터도 기록을 해야 하는 경우 시리얼 모니터로 사용자의 입력을 출력하도록 소스 코드를 작성해야 합니다.

4. 마무리
비록 간략하나마 “Hello, World” 출력 예제를 시작으로, 시리얼 통신을 통한 데이터 입출력 및 빌드, 업로드, 모니터링에 이르는 일련의 과정을 다루었습니다. 이 과정에서 얻으신 경험이 향후 더 복잡한 임베디드 시스템 구현의 밑거름이 되기를 바랍니다. 미흡하나마 본 가이드가 여러분의 ESP32 개발 여정에 작은 도움이 되었기를 진심으로 기대합니다.