M5StickC 가지고 놀거리가 마땅치 않아서 그냥 Sample만 넣어서 가지고 놀다가...
바퀴 달린 장난감을 만들고 싶어졌다. (이건 나중에 BeetleC 소개하겠다)
그런데, 그냥 바퀴 가지고 노는게 아니라
핸드폰으로 조종하는 장난감을 만들고 싶어져서...
M5StickC ~ Android 間 연결 하는 것을 해보려고 한다.
일단 M5StickC 에서 지원하고 있는 Bluetooth Spec은 다음과 같다.
- Integrated dual mode Bluetooth (classic and BLE)
즉, BT / BLE 2가지 모두 되는데... 배터리를 아끼기 위해 BLE를 이용해서 연결해보겠다.
Android Studio를 가지고 앱을 만드는 것은 번거로우니,
가볍게 해보기 위해서 선택한 것은 "앱 인벤터"
이와 관련된 자료를 찾아보다가 찾은 정말 훌륭한 레퍼런스
조금 아쉬운건 M5Stack 기반으로 되어 있어서
M5StickC에서 바로 사용할 순 없고 조금의 수정이 필요했다. 작성해주신 분에게 무한의 감사를~~~~!!!
덕분에 M5StickC 구매한 것을 후회하지 않게 되었다는..... (가지고 놀 방법을 몰라서... 고생을... ㅋㅋㅋ)
- https://bluexmas.tistory.com/972?category=818671
일단 Arduino IDE에서 M5StickC에 넣을 코드를 작성해보자.
#include <M5StickC.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>
#define SERVICE_UUID "454f62bd-2b3e-43de-8cd5-e64f5bc15092"
#define CHARACTERISTIC_UUID "593744ae-3348-44f6-b00f-853e2b3b2b60"
BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
M5.Lcd.println("connected");
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
M5.Lcd.println("disconnected");
deviceConnected = false;
}
};
class MyCallbacks: public BLECharacteristicCallbacks {
void onRead(BLECharacteristic *pCharacteristic) {
M5.Lcd.println("read");
pCharacteristic->setValue("Hello World!");
std::string value = pCharacteristic->getValue();
M5.Lcd.println(value.c_str());
}
void onWrite(BLECharacteristic *pCharacteristic) {
M5.Lcd.println("write");
std::string value = pCharacteristic->getValue();
M5.Lcd.println(value.c_str());
}
};
void setup() {
Serial.begin(115200);
M5.begin();
M5.Lcd.println("BLE start");
BLEDevice::init("M5StickC");
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID);
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
pCharacteristic->setCallbacks(new MyCallbacks());
pCharacteristic->addDescriptor(new BLE2902());
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
}
void loop() {
if (deviceConnected) {
if(M5.BtnA.wasPressed()) {
M5.Lcd.println("Btn A press!");
pCharacteristic->setValue("Btn A press!");
pCharacteristic->notify();
}else if(M5.BtnB.wasPressed()) {
M5.Lcd.println("Btn B press!");
pCharacteristic->setValue("Btn B press!");
pCharacteristic->notify();
}
}
M5.update();
}
레퍼런스로 삼았던 "파란크리스마스"의 포스팅 내용과 함께,
구글링을 통해 확인한 BLE Sample 코드들을 확인하고, M5StickC에서 돌아갈 수 있도록 수정해봤다.
그런데, 일단 시작하기에 앞서서 UUID를 생성해야 한다.
이걸 왜 생성해야하냐고!?
나도 잘 몰라서 찾아봤다.
UUID (Universally Unique IDentifier) 는 우리말로 바꿔보면 "범용 고유 식별자"라고 한다.
결국은 기기 間 통신을 할 때 각 개체를 구분하기 위한 고유값인데,
이러한 고유값은 보통 중앙 관리 시스템에 의해서 관리가 되지만,
여러 사정으로 개발 주체가 스스로 이름을 정하도록 하되 중복되지 않도록 기준을 잡아주고 운영하는 방식이 바로 UUID라고 한다.
완벽히 중복되지 않는다는 보장을 할 수는 없지만, 중복될 가능성이 거의 없기에 많이 사용된다고 한다.
UUID는 16진수 36개 문자로 표현되며 8-4-4-4-12 와 같은 형식으로 구성된다.
- Sample: 454f62bd-2b3e-43de-8cd5-e64f5bc15092
UUID 버전 구성은 아래와 같다.
- 버전 1 (MAC 주소)
- 버전 2 (DCE 보안)
- 버전 3 (MD5 해시)
- 버전 4 (랜덤)
- 버전 5 (SHA-1 해시)
그냥 막 만들려면 막연하니 아래 사이트에서 generate 하고 사용하자.
- https://www.uuidgenerator.net/
버전4로 2개 생성해서 코드의 저 위에 넣어주면 된다.
귀찮으면 그대로 사용해도 되지만 그러면 필자의 디바이스와 혼선이 생길.......리가 없나!? 설마 이웃은 없을테니... ^^
그 다음으로 BLE를 사용하려다보니 뭘 알아야 할 것 같아서 살짝 공부 좀 해봤다.
[ GATT (Generic Attribute Profile) ]
- GATT는 두 BLE 장치간에 Service, Characteristic 을 이용해서 데이터를 주고 받는 방법을 정의한 것입니다.
[ Attribute Protocol (ATT) ]
- GATT는 ATT의 최상위 구현체이며 GATT/ATT로 참조되기도 합니다. 각각의 속성(Attribute)은 UUID를 가지며 128비트로 구성됩니다.
- ATT에 의해 부여된 속성은 특성(characteristic)과 서비스(Service)를 결정합니다.
[ Service ]
- 하나의 서비스는 특성들의 집합입니다.
예를 들어 "Heart Rate Monitor"라고 불리는 서비스를 가지고 있다면 그 서비스는 "heart rate measurement"같은 특성을 포함합니다.
[ Characteristic ]
- 하나의 특성(characteristic)은 하나의 값과 n개의 디스크립터를 포함합니다.
[ Descriptor ]
- 디스크립터는 특성의 값을 기술합니다.
이제, 위의 코드에서 나오는 Service와 Characteristic을 이해할 수 있다 !!! (정말!?)
이제 Android 폰에 넣을 App을 만들어보자!!!
앱 인벤터 (App Inventor)
- https://appinventor.mit.edu/
인벤터에서 BLE 기능을 사용하기 위해서는 Extension을 등록해야 한단다. (아직은 베타?!)
- https://mit-cml.github.io/extensions/
BluetoothLE.aix 파일을 다운로드 받아놓자.
이제 인벤터를 실행해서 새로운 프로젝트를 만들어 보자.
앱 인벤터를 한 번도 사용하지 않았더라도 무서워할 것 없다.
그냥 크롬 브라우져로 접속해서 사용하면 된다.
다만, 눈치만 조금 있다고 하면 아래 그림 보고 잘 따라올 수 있다~^^ (눈치가 부족하신 분은 구글링을 조금.....^^)
그리고, 방금 다운로드 받은 BLE Extension을 등록하자.
그리고 이제 화면을 꾸미면 된다.
왼쪽 팔레트에서 원하는 것을 선택한 뒤에 드래그앤드롭 하면 된다.
이제 블록으로 넘어가서 ...
처음 해보시는 분들은 조금 고생할 수도 있지만
그래도 계속 해보면 된다!!!
필자도 했는데... 여러분은 못할리가 없다~~!!
(파란크리스마스님 다시 한 번 쌩유~~~!!!!)
빌드를 실행하면,
아래와 같이 다운로드 받을 수 있는 QR Code가 나오는데....
이상하게도 필자는 다운로드가 안되서, 그냥 아래 링크 주소 타이핑해서 다운로드 받았다.
이제 실행해보자.
M5StickC 켜져있는 상태 & App 실행상태이다.
앱에서 "조회" 버튼 누른 후, "BLE 기기 선택" 버턴을 눌러보자.
M5StickC 항목이 보일 것이다. 선택하자.
M5StickC에서 connected 되었다는 메시지도 보이고,
앱에서도 BLE 연결이라는 체크박스와 함께 밑에 연결된 디바이스 이름도 보인다.
M5StickC에서 A 버튼을 눌러보자.
B 버튼도 눌러보자.
앱에서 텍스트 입력 후 "보내기" 버튼을 누르면 M5StickC로도 날라가는 것을 볼 수 있다.
에고... 힘들었다.
모르는걸 하려다 보니 이것 저것 알아보고 공부하고 하느라 시간이 꽤 걸렸다.
그래도 뭐 여하튼 되긴 했으니~!!!
Sample Code는 아래 링크에서 다운로드 받을 수 있다.
- https://github.com/what-want/BLEconnect