본문 바로가기
mcu/arduino

아두이노에서 HM-10 다루기

by monotics 2021. 4. 10.

아두이노 나노와 HM-10으로 LED와 가변저항을 원격 제어해본다.

  • 안드로이드 폰에서 원격으로 LED를 제어한다. (밝기 조절, 켜고 끄기, 깜박임)
  • 가변저항의 아날로그 값을 안드로이드 폰으로 보낸다.


HM-10은 Bluetooth 4.0으로 BLE를 지원한다. 알리에서 $4 정도의 싼 가격에 구매할 수 있다. HM-10과 호환되면서 더 저가의 모듈인 AT-09도 있다. HM-10은 센트럴(Central)과 페리페럴(Peripheral) 역할 모두 지원한다. 여기서는 HM-10을 페리페럴 역할로, 안드로이드 폰을 센트롤 역할로 사용한다.

LED와 가변저항을 아두이노 나노와 연결하여 입출력을 원격으로 제어해본다. LED는 원격의 커맨드를 받아 밝기 조절, 켜고 끄기 그리고 깜박임을 제어해보고 가변저항으로는 아날로그 값을 입력받아 원격의 안드로이드 폰으로 전송해본다.

먼저 준비물부터 살펴보자. 

준비물

  • Arduino Nano
  • HM-10 BLE module : 내부 레벨 컨버터가 있는 제품으로 구매하면 따로 레벨 컨버터가 필요 없다.
  • 가변저항 (B10K)
  • LED와 330Ω 저항
  • 브레드보드 및 와이어

HM-10

결선

아두이노 나노를 중심에 두고 HM-10, LED, 가변저항을 연결한다.

아두이노 나노 주변 모듈 설명
D9 HM-10의 Tx 핀 SoftwareSerial을 사용하므로 임의의 디지털 핀에 연결한다.
D10 HM-10의 Rx 핀
~D3 LED 밝기 조절을 위해 PWM이 가능한 ~D3에 연결한다.
A0 가변저항의 가운데 핀 아날로그 값을 입력으로 받는다.

 

아두이노 나노, HM-10, LED, 가변저항 결선

프로젝트 생성

개발은 Visual Studio Code에 PlatformIO 확장을 설치하여 진행하였다. 그럼 PlatformIO에서 프로젝트를 생성해 보자.

  • PlatformIO 홈 > 좌측 'Projects' 탭 클릭 > 우측 상단의 'Create New Project' 클릭
  • 'Project Wizard' 창에 아래와 같이 설정
• 'Name' 필드에 원하는 프로젝트 이름을 입력한다.
• 'Board' 필드에 'Arduino Nano ATmega328' 선택한다.
• 'Framework' 필드에 'Arduino' 선택한다.
• 'Location'을 uncheck 하여 원하는 위치에 프로젝트를 생성할 수 있다.
• 'Finish' 버튼 클릭하여 프로젝트 생성한다.

코드

코드는 각 기능을 담당하는 cpp 파일로 분리하여 작성하였다.

  • main.cpp : HM-10을 초기화하고 루프를 돌면서 커맨드 처리와 데이터 전송을 처리한다. 
  • ble.cpp : SoftwareSerial을 이용하여 HM-10을 다룬다.
  • led.cpp : LED를 제어한다.
  • control.cpp : HM-10을 통해 받은 커맨드를 처리한다.

코드의 중요 부분들을 살펴보자.

SoftwareSerial와 AT Command를 사용하여 HM-10을 초기화한다. AT Command는 센터랄 장치와 연결되기 전에 유효하므로 초기화 때 수행해야 한다.

#include <SoftwareSerial.h>

SoftwareSerial mySerial(PIN_TX, PIN_RX); // D9, D10

void sendCommand(const char * command) {
  mySerial.println(command);
  // wait some time
  delay(500);
}

void initBle() {
  mySerial.begin(9600);

  sendCommand("AT");
  sendCommand("AT+ROLE0"); // Role : 0 -> Peripheral(Slave) (Default)
  sendCommand("AT+UUID0xFFE0"); // Service UUID : 0xFFE0 (Default)
  sendCommand("AT+CHAR0xFFE1"); // Characteristic UUID : 0xFFE1 (Default)
  sendCommand("AT+NAMEBleTest"); // Device Name : "BleTest"
}

센트럴로부터 커맨드 데이터를 받기 위해서는 서로 약속을 정해야 한다. 여기서는 아래 표와 같이 커맨드를 4개의 부분으로 정한다. 시작은 항상 CMD_START(0x01)로 시작하며 원하는 기능은 'COMMAND TYPE'으로 정한다. 'DATA'는 가변 길이이므로 길이 정보를 위해 'DATA LENGTH' 필드를 사용한다.

LED 제어의 경우 TYPE_LED_SW, TYPE_LED_DIM, TYPE_LED_BLINK 커맨드 타입들이 있다.

  • TYPE_LED_SW : LED의 On/Off 한다. Data 값이 1이면 LED를 On, 0이면 Off 시킨다.
  • TYPE_LED_DIM : LED의 밝기를 조절한다. 0~255의 Data 값으로 LED의 밝기 값으로 사용한다.
  • TYPE_LED_BLINK : LED의 깜박임을 제어한다. Data의 첫 번째 바이트로는 깜박이는 횟수를 지정하고 나머지 두 바이트는 깜박이는 주기를 지정한다.
START COMMAND TYPE DATA LENGTH DATA
0x01 : CMD_START 0x11 : TYPE_LED_SW
0x12 : TYPE_LED_DIM
0x13 : TYPE_LED_BLINK
DATA의 길이 가변 길이  DATA
#define CMD_START 0x1

#define BIT_START  0
#define BIT_TYPE   1
#define BIT_LENGTH 2
#define BIT_DATA   3

#define TYPE_LED_SW       0x11
#define TYPE_LED_DIM      0x12
#define TYPE_LED_BLINK    0x13
void executeCommand(int cmd[]) {
  switch(cmd[BIT_TYPE]) {
    case TYPE_LED_SW:
      ledSwitch(cmd[BIT_DATA]);
      break;
    case TYPE_LED_DIM:
      ledDim(cmd[BIT_DATA]);
      break;
    case TYPE_LED_BLINK:
      ledBlink(cmd[BIT_DATA], cmd[BIT_DATA+1] << 8 | cmd[BIT_DATA+2]);
      break;
  }
}

loop() 함수에서는 가변저항의 아날로그 값을 읽어 센터랄 장치인 안드로이드 폰으로 보낸다. loop()가 호출될 때마다 이 과정을 실행하면 너무 자주 수행되므로 millis()를 사용하여 매 500ms마다 처리되도록 한다. 또한 아날로그 값이 이전 값과 같다면 스킵한다. 한 바이트를 보내기 위해 map() 함수로 0~1023 값을 0~255 값으로 변환하였다.

  // send analog value to central every 500ms
  currTime = millis();
  if(currTime - prevTime > 500) {
    prevTime = currTime;
    int data = analogRead(A0);
    data = map(data, 0, 1023, 0, 255);
    if (data != prevData) {
      sendBleData(data); // send 1 byte
      prevData = data;
    }
  }

 

전체 코드는 github에 올려두었다.

테스트

코드를 모두 작성했다면 PlatformIO의 하단 툴바에서 ''를 클릭하여 코드를 빌드한다. 빌드에 성공하면 '→'를 클릭하여 바이너리를 업로드한다. 아직 센트럴 장치와 연결되기 전이라 HM-10의 LED가 깜박인다. 그리고 하단의 플러그 모양을 클릭하면 시리얼 모니터가 열리고 AT command들이 출력되는 것을 볼 수 있다. PlatformIO는 연결된 시리얼 포트를 자동으로 감지하여 연결한다. 만약 PC에 2개 이상의 시리얼 장치가 연결되어 있다면 하나를 선택할 수 있도록 가이드가 나오는데 맞는 포트를 선택하면 된다.

PlatformIO의 하단 툴바에는 개발에 필요한 버튼들을 제공한다.

PlatformIO 하단 툴바

테스트를 위해서는 HM-10과 연결하여 데이터를 주고받을 안드로이드 앱이 있어야 한다. 구글 플레이 스토어에서 nRF Connect for Mobile 앱을 설치한다. 이 앱은 블루투스 칩으로 유명한 '노르딕 세미컨덕터(Nordic Semiconductor)'에서 만든 앱으로 범용으로 사용할 수 있다. 앱을 실행시키면 자동으로 스캔을 시작한다. 앞에서 AT Command로 설정한 HM-10의 장치 명인 'BleTest'가 검색된 것을 볼 수 있다. 'CONNECT' 버튼을 클릭하면 HM-10의 BLE Service UUID로 설정한 '0xFFE0'가 하단에 보인다. 이 Service를 클릭하면 Characteristic UUID로 설정한 '0xFFE1'이 보인다.

HM-10과 연결

데이터를 원격의 HM-10으로 보내보자.

Characteristic의 '↥' 버튼을 클릭하면 'Write value' 창이 나타난다. 드롭다운 리스트에서 Data Type을 'BYTE ARRAY'로 지정한다. 예를 들어, LED를 ON 시키기 위해 '0x01110101'을 입력하고 'SEND' 버튼을 클릭하면 LED가 켜진다. 동일한 값을 나중에 다시 사용하고 싶다면 'SAVE' 버튼을 클릭하여 명령을 저장하면 된다.

LED On command

LED 테스트를 위한 커멘드들은 아래와 같다.

LED 테스트 Command START CMD TYPE LENGTH DATA0 DATA1 DATA2
On 0x01110101 0x01 0x11 0x01 (길이 1) 0x01 (On)    
Off 0x01110100 0x01 0x11 0x01 (길이 1) 0x00 (Off)    
밝기 50% 0x01120180 0x01 0x12 0x01 (길이 1) 0x80 (50%)    
500ms 주기로 5회 깜박이기 0x0113030501C0 0x01 0x13 0x03 (길이 3) 0x05 (5회) 0x01C0 (500ms)

HM-10으로부터 데이터를 읽어보자.

보드의 가변저항 노브를 돌리면 'Value' 필드의 값이 변하는 것을 볼 수 있다.

    •  

아날로그 값 읽기


참고 사이트

Arduino Nano와 HM-10 사용한 프로젝트:

 

BlueCArd - part 5 - Arduino Nano Bluetooth module how to (AT-09 or HM-10)

How to connect and configure a Bluetooth module to communicate with Arduino

www.thinker-talk.com

HM-10 자료:

 

Huamao Technology CO,. LTD.

 

www.jnhuamao.cn

HM-10의 자세한 사용 설명:

 

HM-10 Bluetooth 4 BLE Modules | Martyn Currey

Since I first posted about the HM-10 the firmware has been updated many times and some of the commands have changed. Therefore, I decided to redo the guide. For the main article I am using modules with firmware 5.49 (regular) except the one I am using for

www.martyncurrey.com

 

'mcu > arduino' 카테고리의 다른 글

아두이노 IDE에서 여러 소스 파일 사용  (0) 2021.03.04

댓글