본문으로 이동

아두이노:2.4GHz 송수신

학교의 모든 지식. SMwiki
Sam (토론 | 기여)님의 2026년 7월 23일 (목) 14:51 판 (새 문서: {{아두이노}} == 개요 == 2.4GHz ISM 밴드는 별도의 사용 허가(라이선스) 없이 누구나 쓸 수 있는 주파수 대역으로, Wi-Fi·블루투스와 동일한 대역이다. == 왜 2.4GHz인가? == === 원래는 "버려진 쓰레기 대역"이었다 (역사적 이유) === 전자레인지, 산업용 가열기, 의료용 투열기 같은 기기가 부산물로 RF 에너지를 내뿜는 대역이었음. 이미 노이즈가 심한 대역이라, 규제 당국이...)
(차이) ← 이전 판 | 최신판 (차이) | 다음 판 → (차이)

아두이노 관련 정보를 모으기 위한 틀. 틀:아두이노

  1. 아두이노:개요
  2. 아두이노:하드웨어
    1. 아두이노:우노보드
    2. 아두이노:ESP32
  3. 아두이노:코드
    1. 아두이노:컴퓨터에서 보드로
    2. 아두이노:안드로이드에서 보드로
    3. 아두이노:기초 문법
    4. 아두이노:라이브러리
  4. 아두이노:핀 사용
    1. 아두이노:전원공급
  5. 아두이노:시리얼 통신
    1. 아두이노:엑셀기록
    2. 아두이노:파이썬과 통신
  6. 아두이노:편의함수
  7. 센서 사용
    1. 아두이노:모션센서(미완)
    2. 아두이노:온습도센서
    3. 아두이노:조도센서(미완)
    4. 아두이노:인체감지센서(미완)
    5. 아두이노:pH미터 만들기(Gravity 아날로그 pH센서)
    6. 가스센서
      1. 아두이노:MOS 센서
  8. 아두이노:LCD 사용
  9. 아두이노:스위치 사용
  10. 아두이노:릴레이
  11. 통신 관련, 정보 교환
    1. 아두이노:2.4GHz 송수신
      1. 아두이노:WIFI
      2. 아두이노:블루투스(외장모듈)
      3. 아두이노:RF통신 nRF24L01+
    2. 아두이노:IR 송수신
    3. 아두이노:RFID
  12. 아두이노:해결되지 않은 다양한 의문들
  13. 수업용 간단 실습
    1. 아두이노:LED
    2. 아두이노:초음파센서
    3. 아두이노:전압계 만들기
    4. 아두이노:저항계 만들기
  14. 아두이노 모터 출력
    1. 아두이노:서보 모터
    2. 아두이노:DC 모터
    3. 아두이노:BLDC 모터
  15. 미완문서
    1. 아두이노:스테핑 모터(미완)
  16. 분류:아두이노 프로젝트

개요

2.4GHz ISM 밴드는 별도의 사용 허가(라이선스) 없이 누구나 쓸 수 있는 주파수 대역으로, Wi-Fi·블루투스와 동일한 대역이다.

왜 2.4GHz인가?

원래는 "버려진 쓰레기 대역"이었다 (역사적 이유)

전자레인지, 산업용 가열기, 의료용 투열기 같은 기기가 부산물로 RF 에너지를 내뿜는 대역이었음. 이미 노이즈가 심한 대역이라, 규제 당국이 "어차피 시끄러우니 통신에 써도 되게 열어주자"고 개방한 것. 전자레인지가 2.45GHz에서 동작하기 때문에 이 대역은 이미 간섭에 "희생된" 상태였고, 그래서 오히려 부담 없이 통신용풀렸다.

무면허 개방 (법적/제도적 이유)

결정적 전환점은 1985년 5월 9일 미국 FCC가 2.4GHz를 무면허 대역으로 개방한 사건. 이때 라이선스 없이도 최대 1W 출력의 무선 기기를 시장에 내놓을 수 있게 되었고, 이것이 훗날 Wi-Fi(1997)와 블루투스(1998) 탄생의 토대가 되었다.

그런데, 물리적으로도 좋아.

  • 안테나 크기: 주파수가 높을수록 파장이 짧아져 안테나가 작아진다. 2.4GHz의 파장은 약 12.5cm라, 마우스·이어폰 같은 소형 기기에 탑재 가능. + 정상파는 파장의 1/2이면 충분하고, + 접지면으로 인해 거리가 2배가 되는 효과라 결과적으로 파장의 1/4만 있어도 안테나로 기능이 가능한데,(3cm정도로도 기능) + 유전률이 높은 기판을 쓰면 빛의 속도가 감소하여 유효파장이 줄어들어 더 작게 만들 수 있다. + 접으면 효율이 떨어지지만 공진은 여전히 유지가 되어 또 더 작게 만들 수 있다.
  • 대역폭/데이터 속도: 낮은 주파수(예: 433MHz)보다 넓은 대역폭을 확보할 수 있어 더 빠른 전송이 가능합니다.
  • 투과성/도달거리: 5GHz보다 파장이 길어 벽 통과와 회절이 유리합니다. 더 높은 주파수는 빠르지만 장애물에 약하고, 더 낮은 주파수는 잘 뚫지만 안테나가 커지고 느립니다. 2.4GHz가 그 중간입니다.

활용 예시

  • RC 송신기(조종기) 제작
  • 무선 기상 관측소(센서 데이터 원격 수집)
  • 로봇·드론 원격 제어
  • 홈 오토메이션 및 센서 네트워크

사용 모듈

nRF24L01+ 모듈 규격

nRF24L01+ 모듈은 이 대역에서 동작하는 GFSK 방식의 반이중(half-duplex) 트랜시버로, 한 순간에는 송신 또는 수신 중 하나만 수행하지만 소프트웨어적으로 역할을 빠르게 전환해 양방향 통신을 구현할 수 있다.[1] 주요 특징:

  • 초저전력: 송신 시 약 12 mA(0 dBm 기준)로 LED 한 개보다 적게 소비하며, 대기 22 µA, 파워다운 900 nA 수준이다.
  • 저가: 모듈당 미화 2달러 내외로 매우 저렴하다.
  • 다중 노드: 최대 125개 채널, 채널당 6개 주소(파이프)를 지원해 하나의 수신 허브가 최대 6개 송신 노드와 통신할 수 있다.
  • 하드웨어 프로토콜: Enhanced ShockBurst 엔진이 패킷 조립, 자동 응답(ACK), 재전송, CRC를 하드웨어에서 처리한다.
주요 사양
항목 표준 모듈 PA/LNA 모듈
동작 주파수 2.400 – 2.525 GHz 2.400 – 2.525 GHz
공급 전압 1.9 – 3.6 V 1.9 – 3.6 V
로직 입력 5 V 허용(tolerant) 5 V 허용
출력 전력 −18 dBm ~ 0 dBm −18 dBm ~ +20 dBm
송신 전류(최대) 약 11.3 mA @ 0 dBm 약 115 mA @ +20 dBm
대기 전류 22 µA 22 µA
파워다운 전류 900 nA 900 nA
데이터 속도 250 kbps / 1 Mbps / 2 Mbps 250 kbps / 1 Mbps / 2 Mbps
페이로드 크기 1 – 32 바이트 1 – 32 바이트
채널 수 126 (1 MHz 간격) 126 (1 MHz 간격)
통신 거리 최대 약 100 m(개활지) 최대 약 1,000 m(외장 안테나)

모듈 종류

  • 기판 안테나형(PCB 안테나): 소형·컴팩트, 개활지 기준 약 100 m. 실내·벽 통과 시 거리 감소.
  • PA/LNA + 외장 안테나형: 전력 증폭기(PA)와 저잡음 증폭기(LNA)를 내장해 최대 약 1 km까지 도달. 전류 소모가 크므로 별도 3.3 V 전원 권장.

배선 (Arduino Uno / Nano 기준)

nRF24L01+ ↔ 아두이노 연결
nRF24L01+ 핀 아두이노 Uno/Nano 핀 비고
VCC 3.3 V 절대 5 V 연결 금지
GND GND
CE D9 (변경 가능) 코드와 일치시킬 것
CSN D10 (변경 가능) 코드와 일치시킬 것
SCK D13 하드웨어 SPI 고정
MOSI D11 하드웨어 SPI 고정
MISO D12 하드웨어 SPI 고정
IRQ (미사용) 인터럽트용, 선택 사항

전원 안정화 (매우 중요)

아두이노 내장 3.3 V 레귤레이터는 전류 공급 능력이 부족해 통신 불안정의 가장 흔한 원인이다.

  • VCC–GND 사이에 10 µF ~ 100 µF 전해 커패시터를 최대한 모듈 가까이 병렬 연결한다.
  • PA/LNA 모듈이나 다수 노드 사용 시 별도 외장 3.3 V 레귤레이터를 권장한다.
  • 어댑터 보드(소켓형)를 쓰면 레귤레이터와 디커플링이 내장되어 편리하다.

동작 원리

SPI 인터페이스

모듈은 SPI 슬레이브로 동작하며, 아두이노(마스터)의 하드웨어 SPI 핀(MOSI, MISO, SCK)에 반드시 연결해야 한다. 여기에 더해 두 개의 제어 핀을 사용한다.

  • CE (Chip Enable): 송신/수신 모드를 활성화하는 핀. 임의의 디지털 핀 사용 가능.
  • CSN (Chip Select Not): SPI 슬레이브 선택 핀. 임의의 디지털 핀 사용 가능.

Enhanced ShockBurst

Enhanced ShockBurst는 하드웨어 기반 프로토콜 엔진으로 다음을 자동 처리한다.

  1. 자동 패킷 조립: 프리앰블, 주소, CRC 필드를 페이로드에 자동 추가.
  2. 자동 응답 및 재전송: 수신 측이 ACK를 자동 전송하며, 송신 측은 ACK를 못 받으면 최대 15회까지 자동 재전송.
  3. 동적 페이로드 길이: 1~32바이트 가변 길이 지원.
  4. 멀티 파이프: 서로 다른 주소를 가진 6개 데이터 파이프를 동시에 수신 대기.

라이브러리 설치

가장 널리 쓰이는 라이브러리는 TMRh20이 유지보수하는 RF24 라이브러리다.

  1. 아두이노 IDE를 연다.
  2. 메뉴에서 스케치 → 라이브러리 포함하기 → 라이브러리 관리를 선택한다.
  3. 검색창에 RF24를 입력하고 TMRh20의 RF24 by TMRh20을 설치한다.

필요한 헤더는 다음과 같다.

#include <SPI.h>       // SPI 통신
#include <nRF24L01.h>  // 레지스터 정의
#include <RF24.h>      // RF24 드라이버 클래스

예제 1: 단방향 통신 ("Hello World")

가장 기본적인 예제로, 송신기가 문자열을 1초마다 보내고 수신기가 시리얼 모니터에 출력한다. 최신 RF24 라이브러리는 주소를 uint64_t 대신 바이트 배열로 지정하는 방식을 권장한다.

송신기 (Transmitter)

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(9, 10);  // CE, CSN 핀

const byte address[6] = "00001";  // 5바이트 주소(파이프)

void setup() {
  Serial.begin(9600);
  if (!radio.begin()) {
    Serial.println(F("무선 모듈이 응답하지 않습니다!"));
    while (1) {}  // 무한 루프로 정지
  }
  radio.openWritingPipe(address);   // 송신 파이프 열기
  radio.setPALevel(RF24_PA_LOW);    // 출력 레벨(테스트 시 LOW 권장)
  radio.setDataRate(RF24_250KBPS);  // 데이터 속도(거리↑, 안정성↑)
  radio.stopListening();            // 송신 모드로 전환
}

void loop() {
  const char text[] = "Hello World";
  bool ok = radio.write(&text, sizeof(text));
  Serial.println(ok ? F("전송 성공") : F("전송 실패"));
  delay(1000);
}

수신기 (Receiver)

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(9, 10);  // CE, CSN 핀

const byte address[6] = "00001";  // 송신기와 동일해야 함

void setup() {
  Serial.begin(9600);
  if (!radio.begin()) {
    Serial.println(F("무선 모듈이 응답하지 않습니다!"));
    while (1) {}
  }
  radio.openReadingPipe(0, address);  // 수신 파이프 0번 열기
  radio.setPALevel(RF24_PA_LOW);
  radio.setDataRate(RF24_250KBPS);
  radio.startListening();             // 수신 모드로 전환
}

void loop() {
  if (radio.available()) {
    char text[32] = "";
    radio.read(&text, sizeof(text));
    Serial.print(F("수신: "));
    Serial.println(text);
  }
}

틀:참고

예제 2: 구조체로 여러 값 한 번에 전송

온도·습도·기압처럼 여러 값을 한 패킷(≤ 32바이트)에 담아 보낼 때 struct를 사용한다.

공통 구조체 정의

struct SensorData {
  byte  id;           // 1바이트
  float temperature;  // 4바이트
  float humidity;     // 4바이트
  int   pressure;     // 2바이트
};  // 총 11바이트 (32바이트 이하)

송신기

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(9, 10);
const byte address[6] = "00001";

struct SensorData {
  byte  id;
  float temperature;
  float humidity;
  int   pressure;
};

SensorData data;

void setup() {
  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_LOW);
  radio.stopListening();
}

void loop() {
  data.id = 1;
  data.temperature = 24.5;
  data.humidity    = 55.2;
  data.pressure    = 1013;
  radio.write(&data, sizeof(data));
  delay(1000);
}

수신기

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(9, 10);
const byte address[6] = "00001";

struct SensorData {
  byte  id;
  float temperature;
  float humidity;
  int   pressure;
};

SensorData data;

void setup() {
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_LOW);
  radio.startListening();
}

void loop() {
  if (radio.available()) {
    radio.read(&data, sizeof(data));
    Serial.print(F("ID: "));    Serial.print(data.id);
    Serial.print(F("  온도: ")); Serial.print(data.temperature);
    Serial.print(F("  습도: ")); Serial.print(data.humidity);
    Serial.print(F("  기압: ")); Serial.println(data.pressure);
  }
}

예제 3: 양방향 통신 (송수신 전환)

한 노드가 송신과 수신을 번갈아 수행한다. 두 노드는 서로 다른 주소를 쓴다.

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(9, 10);

// 두 개의 주소: 이 노드가 A라면 상대는 B
const byte addresses[][6] = {"NODE1", "NODE2"};

bool isNode1 = true;  // 상대 노드에서는 false로 설정

void setup() {
  Serial.begin(9600);
  radio.begin();
  if (isNode1) {
    radio.openWritingPipe(addresses[1]);     // NODE2로 송신
    radio.openReadingPipe(1, addresses[0]);  // NODE1로 수신
  } else {
    radio.openWritingPipe(addresses[0]);
    radio.openReadingPipe(1, addresses[1]);
  }
  radio.setPALevel(RF24_PA_LOW);
}

void loop() {
  // --- 송신 단계 ---
  radio.stopListening();
  const char msg[] = "PING";
  radio.write(&msg, sizeof(msg));

  // --- 수신 단계 ---
  radio.startListening();
  unsigned long started = millis();
  while (!radio.available()) {
    if (millis() - started > 200) return;  // 200ms 타임아웃
  }
  char reply[32] = "";
  radio.read(&reply, sizeof(reply));
  Serial.print(F("응답 수신: "));
  Serial.println(reply);

  delay(500);
}

주요 함수 정리

RF24 라이브러리 핵심 메서드
함수 설명
radio.begin() 모듈 초기화. 성공 시 true 반환
radio.openWritingPipe(addr) 송신 파이프 주소 설정
radio.openReadingPipe(n, addr) n번(0~5) 수신 파이프 주소 설정
radio.startListening() 수신 모드 진입
radio.stopListening() 송신 모드 진입
radio.write(&buf, len) 데이터 송신(ACK 수신 시 true)
radio.available() 수신 데이터 존재 여부
radio.read(&buf, len) 수신 데이터 읽기
radio.setPALevel(level) 출력 레벨: RF24_PA_MIN / LOW / HIGH / MAX
radio.setDataRate(rate) 속도: RF24_250KBPS / RF24_1MBPS / RF24_2MBPS
radio.setChannel(ch) 채널(0~125) 설정
radio.setRetries(delay, count) 재전송 간격·횟수 설정
radio.printDetails() 디버깅 정보 시리얼 출력

문제 해결 (Troubleshooting)

  • 전송이 계속 실패하거나 데이터가 안 옴 → 전원 문제일 가능성이 가장 큼. VCC–GND에 10~100 µF 커패시터 추가, 외장 3.3 V 전원 사용.
  • 송·수신이 안 됨 → 양쪽의 주소·데이터 속도·채널이 일치하는지 확인.
  • radio.begin()이 false → SPI 배선(MOSI/MISO/SCK) 및 CE/CSN 핀 번호 확인. printDetails()로 레지스터 값이 0x00/0xFF만 나오면 배선 불량.
  • 거리가 짧음 → 데이터 속도를 250 kbps로 낮추고, PA 레벨을 높이거나 PA/LNA 외장 안테나 모듈 사용.
  • 간헐적 끊김 → Wi-Fi(1~11 채널) 간섭 회피를 위해 상위 채널(예: 100번 이상) 사용.

안전 및 규제

  • 2.4GHz ISM 대역은 비면허 대역이나, 출력 및 사용 규정은 국가별로 다를 수 있으므로 고출력 PA/LNA 모듈 사용 시 국내 전파 규정을 확인한다.
  • 다수 모듈을 밀집 배치할 경우 상호 간섭을 줄이기 위해 채널을 분리한다.

같이 보기

각주

  1. How To Mechatronics, "nRF24L01 – How It Works".

외부 링크