
시리얼 터미널로 프로그램의 상태를 PC로 전송하여 마이크로컨트롤러가 무엇을 하고 있는지 알 수 있다. 또한, 다른 장치와 데이터를 주고받거나 바이너리 데이터를 전송하는 데에도 사용할 수 있다.
일반 PC에서 프로그래밍할 때는 디버거 같은 도구를 쉽게 사용할 수 있지만, 마이크로컨트롤러에는 화면이 없는 경우가 많아서 디버깅이 까다롭다. 이때 시리얼 터미널로 변수 값이나 센서 값 등을 출력하면 프로그램이 실제로 무엇을 하고 있는지 쉽게 파악할 수 있다.
또한, 시리얼 통신은 마이크로컨트롤러뿐만 아니라 다양한 임베디드 시스템과 장치에서도 매우 흔하게 사용되는 방식이다. 본 블로그에서는 주로 디버깅과 모니터링을 목적으로 사용하겠지만, 일부 센서는 제어를 위해 시리얼 통신을 직접 사용하기도 한다.
Mbed의 UnbufferedSerial 클래스를 사용할 것이다. 이름으로 BufferedSerial도 있다는 것을 유추할 수 있다.
객체 생성 시, TX 핀, RX 핀, Baud Rate 총 세 가지 인자가 필요하다. 여기서는 인자를 다음과 같이 할 것이다.
UnbufferedSerial pc(USBTX, USBRX, 115200)
참고로 Baud Rate는 전송 속도를 결정한다. 낮은 속도는 안정적이지만 느리고, 높은 속도는 빠르지만 신호 품질에 따른 영향을 받을 수도 있다. 흔히 쓰이는 값은 9600이지만, 본 블로그에서는 마이크로컨트롤러의 기본 설정에 맞는, 더 높은 값(115200)을 사용하겠다.
가장 간단한 방법은 C 표준 함수인 printf을 사용하는 것이다. 일반 PC 프로그램에서는 Console에 출력되지만, Mbed에서는 내부적으로 이 출력이 시리얼 포트로 연결된다.
따라서 printf("Hello World\n");처럼 쓰면, 시리얼 터미널에서 메시지를 확인할 수 있다. 개행 문자를 추가하면 정상적으로 한 줄씩 출력된다.
printf는 변수 값도 출력할 수 있다. 예를 들어, 반복문 내에서 counter 변수를 출력하려면 다음과 같이 할 수 있다.
int counter = 0;
while (true) {
printf("Counter: %d\n", counter);
counter++;
ThisThread::sleep_for(2000);
}
이렇게 하면 2 초마다 counter 값이 출력된다.
printf 외에도, UnbufferedSerial 객체의 write 함수를 직접 사용할 수 있다.
char buffer[] = "Hello\n";
while (true) {
pc.write(buffer, strlen(buffer));
ThisThread::sleep_for(2000);
}
주로 바이너리 데이터를 전송할 때 사용한다.
디지털 신호는 단지 High 혹은 Low 두 가지 값만 가질 수 있다. 반면, 아날로그 신호는 특정 범위 안에서 연속적인 전압 값을 가진다.
즉, 디지털 신호는 이진 값(0 또는 1)만 나타내지만, 아날로그 신호는 시간에 따라 연속적으로 변화하는 값을 가진다. 마이크로컨트롤러는 기본적으로 이진 장치이므로 아날로그 신호를 직접 읽을 수 없고, 이를 디지털로 변환해주는 ADC라는 내부 peripheral을 사용해야 한다.
ADC는 특정 순간의 전압 값을 받아 디지털 값으로 변환한다. 예를 들어 2.2 V라면, 이를 정수 값으로 변환하여 프로세서가 이해할 수 있게 한다.
참고로, ADC에는 해상도(Resolution)라는 개념이 있다. 흔히 12 비트 해상도를 가지며, 이는 입력 전압을 0~4095 사이의 값으로 변환한다는 뜻이다. 해상도가 높을수록 세밀한 측정이 가능하다.
실습 장치에는 Potentiometer가 있으며, 이를 이용해 0 V ~ 3.3 V 범위의 전압을 만들 수 있다. 이 Potentiometer는 마이크로컨트롤러의 ADC 기능이 있는 핀에 연결되어 있다.
실습 장치에는 최대 8 개의 Potentiometer가 있어 동시에 8 개의 아날로그 입력을 읽을 수 있다. 다만, 모든 마이크로컨트롤러 핀이 ADC를 지원하는 것은 아니므로, 실제 회로를 구성할 때는 해당 핀이 ADC 입력을 지원하는지 반드시 확인해야 한다.
#include "mbed.h"
UnbufferedSerial pc(USBTX, USBRX, 112500);
AnalogIn pot1(PC_0);
// Voltage range: 0 - 3.3 V
const float MAX_VOLTAGE = 3.3f;
int main() {
while (true) {
float relativeVoltage = pot1.read();
int millivolts = relativeVoltage * MAX_VOLTAGE * 1000;
printf("Voltage: %d mV\n", millivolts);
ThisThread::sleep_for(2s);
}
}



