대규모 아두이노 프로젝트를 진행할 때 부품을 연결할 수 있는 핀이 부족한 경우가 종종 있습니다. 핀을 많이 사용하는 디스플레이 모듈에 공급하기 위해 여분의 핀을 긴급하게 보존해야 하는 상황에서 여러 센서/액추에이터를 연결하고 싶다고 가정해 보겠습니다.

마법을 부리지 않는 한, 특히 공간에 쫓겨 더 작은 보드를 사용하기로 결정한 경우 단일 Arduino 보드에서 이러한 모든 연결을 처리하는 것이 어려울 때가 있습니다. 이럴 때 직렬 통신이 유용합니다.

직렬 통신이 무엇이며, 분산 처리 및 일반 통합과 같은 작업을 위해 아두이노로 직렬 통신을 설정하는 방법을 살펴봅시다.

직렬 통신이란 무엇인가요?

직렬 통신은 두 개 이상의 전자 장치 간에 단일 통신 회선을 통해 한 번에 한 비트씩 데이터를 송수신하는 방법입니다. 이름에서 알 수 있듯이 데이터는 “직렬”로 전송됩니다.

즐겨 사용하는 아두이노 보드에 스케치를 업로드하는 것만 해도 USB를 통한 직렬 통신을 사용합니다.

아두이노의 직렬 통신 프로토콜

아두이노 보드는 매우 다재다능하며 다양한 장치와 통신할 수 있습니다. 네 가지 직렬 통신 프로토콜을 지원합니다: 소프트 시리얼, SPI(직렬 주변 장치 인터페이스), 표준 UART(범용 비동기식 수신기-송신기), I2C(집적 회로). 자세한 내용은 UART, SPI 및 I2C 직렬 통신의 작동 방식에 대한 종합 가이드를 확인하세요.

이 튜토리얼에서는 기본 스케치를 사용하여 다양한 프로토콜을 사용하여 두 개의 Arduino Uno 보드 간에 직렬 연결을 설정하는 방법을 보여줍니다. 특정 요구 사항에 맞게 코드를 조정하세요.

SPI(직렬 주변 장치 인터페이스)

SPI는 마이크로컨트롤러와 주변 장치 간의 고속 통신을 가능하게 하는 동기식 직렬 통신 프로토콜입니다. 이 프로토콜에는 통신을 위해 4개의 전선이 필요합니다: SCK(직렬 클록), MOSI(마스터 아웃 슬레이브 인), MISO(마스터 인 슬레이브 아웃), SS(슬레이브 선택).

이러한 유형의 통신에 매우 유용한 SPI.h 라이브러리는 스케치 맨 위에 포함되어야 합니다.

 #include <SPI.h> 

다음은 아두이노 우노 보드의 SPI 핀입니다:

기능

핀 번호(디지털)

핀 번호(ICSP 헤더)

MOS

11

4

된장

12

1

sck

13

3

SS

10 (기본값)

1 (대안)

직렬 통신을 초기화한 후입니다, 통신 핀을 구성해야 합니다.

 void setup() {
  SPI.begin(115200);
  // Set pin modes for SS, MOSI, MISO, and SCK
  pinMode(SS, OUTPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(MISO, INPUT);
  pinMode(SCK, OUTPUT);

  // Set slave select (SS) pin high to disable the slave device
  digitalWrite(SS, HIGH);
}

SS 신호는 데이터가 전송될 때 슬레이브 장치에 알리는 데 사용됩니다.

 // Select the slave
digitalWrite(SS, LOW);

// Send data to the slave device
SPI.transfer(data);

// Deselect the slave device
digitalWrite(SS, HIGH);

SPI를 사용하여 두 개의 아두이노 보드를 연결하는 방법은 다음과 같습니다.

이 글도 확인해 보세요:  풀업 저항기란 무엇이며 어떻게 사용하나요?

마스터 보드의 코드입니다:

 #include <SPI.h>
const int slaveSelectPin = 10;
void setup() {
  SPI.begin(115200);
  pinMode(slaveSelectPin, OUTPUT);
}

void loop() {
  digitalWrite(slaveSelectPin, LOW);
  SPI.transfer('H');
  digitalWrite(slaveSelectPin, HIGH);
  delay(1000);
}

슬레이브 보드용 코드:

 #include <SPI.h>
const int slaveSelectPin = 10;
void setup() {
  SPI.begin(115200);
  pinMode(slaveSelectPin, OUTPUT);
}

void loop() {
  if (digitalRead(slaveSelectPin) == LOW) {
    char receivedData = SPI.transfer('L');
    Serial.println(receivedData);
  }
}

적절한 구성을 위해 장치가 공통 접지를 공유하는지 확인하세요.

UART(범용 비동기 수신기-송신기)

UART는 두 개의 전선만 사용하여 장치 간에 통신할 수 있는 비동기 직렬 통신 프로토콜입니다: TX(송신) 및 RX(수신). UART는 일반적으로 GPS 모듈, 블루투스 모듈 및 기타 마이크로컨트롤러와 같은 장치와의 통신에 사용됩니다. 모든 아두이노 보드에는 UART용 포트가 하나 이상 장착되어 있습니다.

인기 있는 아두이노 보드의 UART 핀에는 다음이 포함됩니다:

보드

직렬 핀

직렬1 핀

직렬2 핀

직렬3 핀

Uno, 나노, 미니

0 (RX), 1 (TX)

N/A

N/A

N/A

Mega

0 (RX), 1 (TX)

19 (RX), 18 (TX)

17 (RX), 16 (TX)

15 (RX), 14 (TX)

직렬 통신에 대한 Arduino의 온라인 문서 에서 전체 표를 얻을 수 있습니다.

먼저 보드를 다음과 같이 연결합니다:

그런 다음 발신자 보드에 이 코드를 사용합니다:

 void setup() {
   Serial.begin(9600);
}

void loop() {
  // Send a message over serial every second
  Serial.println("Hello from the sender board!");
  delay(1000);
}

수신기 보드용 코드:

 void setup() {
    Serial.begin(9600);
}

void loop() {
  // Check if there is any incoming data
  if (Serial.available() > 0) {
    // Read the incoming data and print it to the serial monitor
    String incomingData = Serial.readString();
    Serial.println(incomingData);
  }
}

컴퓨터의 RS232 포트는 +/-12V 논리 레벨을 사용하는 반면, Arduino Uno는 5V 논리 레벨에서 작동합니다.

Arduino Uno를 RS232 포트에 직접 연결하면 보드가 손상될 수 있습니다.

I2C(집적 회로)

I2C는 동기식 직렬 통신 프로토콜로, 두 개의 전선만 사용하여 여러 장치 간에 통신할 수 있습니다: SDA(직렬 데이터)와 SCL(직렬 클록). I2C는 일반적으로 짧은 거리에서 데이터를 전송해야 하는 센서, EEPROM 및 기타 장치와의 통신에 사용됩니다.

이 글도 확인해 보세요:  라즈베리 파이에서 호스팅할 수 있는 9가지 종류의 서버

아두이노 우노의 I2C 핀은 SDA(A4) 및 SCL(A5)입니다.

I2C 통신을 사용하여 두 개의 아두이노 보드 사이에 연결을 설정하는 간단한 프로그램을 만들어 보겠습니다. 먼저 보드를 다음과 같이 연결합니다:

마스터 보드의 코드:

 #include <Wire.h>
void setup() {
  Wire.begin(); // join I2C bus as master
  Serial.begin(9600);
}

void loop() {
  Wire.beginTransmission(9); // transmit to slave device with address 9
  Wire.write('a'); // sends 'a' byte to slave device
  Wire.endTransmission(); // stop transmitting

  delay(500);
}

슬레이브 보드용 코드:

 #include <Wire.h>
void setup() {
  Wire.begin(9); // join I2C bus as a slave with address 9
  Wire.onReceive(receiveEvent);
  Serial.begin(9600);
}

void loop() {
  delay(100);
}

void receiveEvent(int bytes) {
  while(Wire.available()) { // loop through all received bytes
    char receivedByte = Wire.read(); // read each byte received
    Serial.println(receivedByte); // print received byte on serial monitor
  }
}

소프트웨어 시리얼이란 무엇인가요?

아두이노 소프트웨어 시리얼 라이브러리는 UART 통신을 에뮬레이션하기 위해 개발되어 아두이노 보드의 디지털 핀 두 개를 통해 직렬 통신이 가능합니다. 다른 장치에서 하드웨어 UART를 이미 사용 중인 경우에 유용합니다.

SoftwareSerial을 설정하려면 먼저 스케치에 SoftwareSerial 라이브러리를 포함하세요.

 #include <SoftwareSerial.h> 

그런 다음 통신에 사용할 RX 및 TX 핀을 지정하여 SoftwareSerial 객체의 인스턴스를 생성합니다.

 SoftwareSerial mySerial(2, 3); // RX, TX pins 

다음은 SoftwareSerial의 사용을 보여주는 Arduino의 예제 코드입니다:

 #include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // RX, TX pins
void setup() {
  Serial.begin(9600); // start hardware serial
  mySerial.begin(9600); // start soft serial
}

void loop() {
  if (mySerial.available()) {
    Serial.write(mySerial.read()); // send received data to hardware serial
  }
  if (Serial.available()) {
    mySerial.write(Serial.read()); // send data from hardware serial to soft serial
  }
}

직렬 라이브러리

직렬 라이브러리는 직렬 연결을 통해 마이크로 컨트롤러와 컴퓨터 또는 기타 장치 간의 통신을 허용하는 Arduino의 강력한 도구입니다. 몇 가지 일반적인 기능은 다음과 같습니다:

이 글도 확인해 보세요:  엘레구, 킥스타터에서 새로운 펙다 레이저 조각기 출시

Function

설명

Serial.

지정된 데이터 전송률로 직렬 통신을 초기화합니다.

Serial.print(data)

데이터를 직렬 포트로 전송하여 ASCII 텍스트로 전송합니다.

Serial.write(data)

직렬 포트를 통해 원시 바이너리 데이터를 전송합니다.

Serial.available()

직렬 버퍼에서 읽을 수 있는 바이트 수를 반환합니다.

Serial.flush()

보내는 직렬 데이터가 전송을 완료할 때까지 기다렸다가 계속합니다.

Serial.read()

들어오는 직렬 데이터의 첫 바이트를 읽고 정수로 반환합니다.

전송 속도 및 직렬 데이터 형식

전송 속도는 직렬 연결을 통해 데이터가 전송되는 속도를 말합니다. 초당 전송되는 비트 수를 나타냅니다. 송신 장치와 수신 장치 모두에서 전송 속도를 동일하게 설정해야 하며, 그렇지 않으면 통신이 왜곡되거나 전혀 작동하지 않을 수 있습니다. 아두이노의 일반적인 전송 속도에는 9600, 19200, 38400 및 115200이 있습니다.

직렬 데이터 형식은 직렬 연결을 통해 전송되는 데이터의 구조를 나타냅니다. 직렬 데이터 형식에는 시작 비트, 데이터 비트, 정지 비트의 세 가지 주요 구성 요소가 있습니다.

⭐ 데이터 비트: 단일 데이터 바이트를 나타내는 데 사용되는 비트 수입니다.

⭐ 패리티: 오류 검사에 사용되는 선택적 비트입니다. 통신 채널의 요구 사항에 따라 없음, 짝수 또는 홀수 패리티로 설정할 수 있습니다.

⭐ 정지 비트: 데이터 바이트의 끝을 알리는 데 사용되는 비트 수입니다.

데이터 형식은 송신 장치와 수신 장치 모두에서 동일해야 제대로 통신할 수 있습니다. 다음은 특정 데이터 형식을 설정하는 방법의 예입니다:

 void setup() {
  // Set up serial communication with 9600 baud rate, 8 data bits, no parity, and 1 stop bit
  Serial.begin(9600, SERIAL_8N1);
}

여기서 SERIAL_8N1은 8개의 데이터 비트, 패리티 없음, 1개의 스톱비트가 있는 데이터 형식을 나타냅니다. 프로젝트의 특정 요구 사항에 따라 SERIAL_7E1, SERIAL_8O2 등과 같은 다른 옵션을 사용할 수 있습니다.

시리얼 토크

아두이노 보드는 장치 간에 효율적이고 안정적인 데이터 교환을 가능하게 하는 다양한 직렬 통신 옵션을 제공합니다. 아두이노 IDE에서 직렬 통신 프로토콜을 설정하는 방법을 이해하면 분산 처리 기능을 활용하거나 프로젝트에 사용되는 전선 수를 크게 줄일 수 있습니다.

By 김민수

안드로이드, 서버 개발을 시작으로 여러 분야를 넘나들고 있는 풀스택(Full-stack) 개발자입니다. 오픈소스 기술과 혁신에 큰 관심을 가지고 있고, 보다 많은 사람이 기술을 통해 꿈꾸던 일을 실현하도록 돕기를 희망하고 있습니다.