레이블이 사물인터넷인 게시물을 표시합니다. 모든 게시물 표시
레이블이 사물인터넷인 게시물을 표시합니다. 모든 게시물 표시

2021년 1월 23일 토요일

저가 IoT 장치 개발을 위한 통합 임베디드 모듈 TTGO WiFi Bluetooth ESP32 개발 방법 및 사용기

이 글은 그 동안 리뷰 미루어 두었던, 통합 무선 모듈 TTGO WiFi Bluetooth ESP32 개발 방법 및 사용기를 간단히 나눔한다. 

이 모듈은 GPIO16, WiFi, Bluetooth, OLED, 충전식 배터리 장치를 모두 포함하고도 겨우 10달러 아래에 구입할 수 있는 ESP32 칩 기반 소형 임베디드 컴퓨터이다. 18650 소형 배터리를 지원하며, 프로그래밍은 아두이노 IDE에서 코딩할 수 있다. 이런 기능을 통해, 손쉽게 저가의 IoT 장치를 개발할 수 있다.

다음 영상은 이 모듈을 이용해 개발한 사례를 보여준다.

개발 사례(TTGO WiFi & Bluetooth Battery ESP32 0.96 inch OLED development tool)
날씨 측정을 위한 웨더스테이션 개발 사례

ESP32 보드
TTGO ESP32에 사용된 메인칩인 ESP32는 Wi-Fi, Bluetooth가 통합된 칩 마이크로 컨트롤러이며, 저가형 저전력 시스템이다. 참고로, TTGO는 www.lilygo.cn 브랜드이며, 중국 심천의 보드 회로 메이커이다. ESP32 시리즈는 Tensilica Xtensa LX6 마이크로 프로세서를 사용해 내장 안테나 스위치, RF, 필터 및 전력 관리 모듈을 포함하고 있다. ESP32는 상하이에 본사를 둔 중국 회사인 Espressif Systems가 개발했으며 TSMC에서 40nm 공정을 사용하여 제조된다. 이 칩은 ESP8266 마이크로 컨트롤러의 후속 제품이다.

ESP32 칩 기반 보드는 주변에 어떤 모듈을 추가했느냐에 따라 다음 그림과 같이 다양한 변종이 존재한다. TTGO WiFi Bluetooth ESP32 모듈은 ESP32 칩 기반 모듈 중 무선 통신 및 OLED 기능을 가지고 있다.

ESP32 모듈의 GPIO 레이아웃 구조는 다음과 같다. 

모듈 스펙
이 모듈은 다음과 같은 형태로 디자인되어 있다. 앞면은 OLED, WiFi, GPIO등이 보이고, 뒤면은 18650배터리를 장착할 수 있도록 되어 있다.
ESP32 보드와 18650 배터리

이 모듈의 자세한 스펙은 다음과 같다. 
  • Micro USB 입력
  • Integrated 18650 충전 지원
  • SDA OLED, SCL은 D1 pin, D2 pin과 연결됨
  • 인터럽트 / pwm / I2C 지원
  • Integrated OLED 지원
  • Input voltage range: 5-12V. Charge current: 500 mA
다음은 18650 배터리 사용 시 주의사항이다. 
If the battery is in the wrong direction, the charging chip will be destroyed.
When you burn a program. Please disconnect the battery and check that the switch is in position.

아두이노 IDE 설정 및 사용 방법
다음 순서로 아두이노 IDE를 설정한다. 우선, 개발보드를 추가해야 하고, 그 다음 라이브러리를 추가해 예제를 실행해 본다.

1. 모듈과 컴퓨터를 USB 케이블로 연결한다. 그리고, FILE > 환경 설정 메뉴에서 다음 링크를 추가한다.

2. 아두이노 IDE에서 Tools > Board > Boards Manager 메뉴를 선택하고 ESP32 를 검색한 후보드를 설치한다. 

BOARD IN ESP32 BY Espressif

3. 다음과 같이 WEMOS LOLIN32 보드를 선택한다. 그리고, 연결된 COM 포트를 선택한다.

4. 아두이노 IDE에서 FILE > EXAMPLE > ESP32 메뉴의 BLUETOOTH 예제를 선택한다.

5. 아두이노 IDE에서 UPLOAD 버튼을 클릭한다. 이때, 보드의 BOOT BUTTON을 누르고 있어야 한다. 모듈의 PORT 0 과 GND를 서로 연결해도 동일하게 동작한다. 만약, 버튼을 누르지 않으면, 다음과 같은 에러가 발생하고, 코드가 모듈로 업로드되지 않는다.

ESP32 Timed out 문제
코드 업로드 장면(Boot 버튼 푸시 후 코드 업로드되면 EN버튼 푸시할 것)

이 문제에 대한 좀 더 상세한 내용은 다음 링크를 참조한다.

6. 코드가 다 업로드되면, BOOT 버튼를 놓고, 모듈의 EN 버튼을 클릭한다. 그럼, 코드가 동작할 것이다. 

7. 아두이노 IDE의 시리얼 모니터 메뉴를 선택하면, 예제 코드에서 출력되는 내용을 확인할 수 있다. 다음과 같이 모듈에서 획득한 BLUETOOTH 스캔 결과를 데이터로 볼 수 있을 것이다. 


동작 결과

다른 ESP32 모듈 예제는 FILE > EXAMPLE > ESP32 메뉴에서 실행해 본다. 

OLED 디스플레이 예제
내장된 디스플레이에 그림을 출력해 본다. 디스플레이 칩은 SSD1306이다. 사용을 위해 다음과 같이 라이브러리를 추가한다.

그리고, 새파일을 만든 후, 다음 소스코드를 복사해 붙여 넣는다.
/*********
  Complete project details at https://randomnerdtutorials.com  
*********/

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

static const uint8_t image_data_Saraarray[1024] = {
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x14, 0x9e, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x36, 0x3f, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x6d, 0xff, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0xfb, 0xff, 0x80, 0x1f, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x03, 0xd7, 0xff, 0x80, 0x0f, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x07, 0xef, 0xff, 0x80, 0x07, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x0f, 0xdf, 0xff, 0x90, 0x07, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x0f, 0xbf, 0xff, 0xd0, 0x07, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x1d, 0x7f, 0xff, 0xd0, 0x07, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x01, 0x1b, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x02, 0xa7, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x03, 0xff, 0xc0, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0xff, 0x80, 0x00, 0x0b, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x07, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0f, 0x07, 0xff, 0xf8, 0xf8, 0x03, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0e, 0x01, 0xff, 0xc0, 0x38, 0x07, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1c, 0x46, 0xff, 0xb1, 0x18, 0x07, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x3f, 0x97, 0xff, 0xc0, 0x7a, 0x07, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xfe, 0x03, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xfe, 0x03, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xfe, 0x01, 0x3f, 0xff, 0xff, 0xff, 0xfe, 0x01, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xfe, 0x01, 0xbf, 0xff, 0xff, 0xff, 0xfe, 0x81, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0xbf, 0xff, 0xff, 0xff, 0xfc, 0x81, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0xff, 0xff, 0xfe, 0xff, 0xfd, 0x83, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0xbf, 0xff, 0xfe, 0xff, 0xfd, 0x01, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xfb, 0x03, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x3f, 0xff, 0xdc, 0xff, 0xfa, 0x03, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xd8, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xd0, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0x90, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xf8, 0x02, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xb0, 0x00, 0x0f, 0xf5, 0xff, 0xd7, 0xf8, 0x01, 0xff, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xb0, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x5f, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xa0, 0x00, 0x0f, 0xfb, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x0f, 0xfd, 0xff, 0xdf, 0xf0, 0x00, 0x3f, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x07, 0xff, 0xff, 0xbf, 0xf0, 0x00, 0x0f, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x07, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x87, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x03, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x43, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0x60, 0x00, 0x01, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x73, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xfe, 0xe0, 0x00, 0x00, 0xff, 0xff, 0xff, 0x80, 0x00, 0x7b, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xfd, 0xe0, 0x00, 0x00, 0x7f, 0xff, 0xfe, 0x00, 0x00, 0x33, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xfd, 0xe0, 0x00, 0x00, 0x3f, 0xff, 0xf8, 0x00, 0x00, 0x27, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0x60, 0x00, 0x00, 0x67, 0xff, 0xe0, 0x00, 0x00, 0x1b, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xfd, 0x40, 0x00, 0x00, 0xf3, 0xff, 0xc4, 0x00, 0x00, 0x0b, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xfe, 0x80, 0x00, 0x00, 0xfc, 0xff, 0x8c, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x7f, 0x3c, 0x3c, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x7c, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 
    0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xfc, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff
};
 
void setup() {
  Serial.begin(115200);
  
  // Start I2C Communication SDA = 5 and SCL = 4 on Wemos Lolin32 ESP32 with built-in SSD1306 OLED
  Wire.begin(5, 4);

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C, false, false)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  delay(2000); // Pause for 2 seconds
 
  // Clear the buffer.
  display.clearDisplay();
  
  // Draw bitmap on the screen
  display.drawBitmap(0, 0, image_data_Saraarray, 128, 64, 1);
  display.display();
}
 
void loop() {
  
}

앞서 했던 것처럼, TTGO ESP32보드에 코드를 업로드한다. 그럼, 다음과 같이 OLED에 출력된 그래픽을 확인할 수 있다.

기타 예제는 다음 github를 참고한다.
충전 및 사용
TTGO 모듈은 충전기가 내장되어 있다. 18650 배터리 (2600mAh)를 테스트해본 결과, OLED LCD를 계속 동작시킨 상태에서 2일정도를 사용할 수 있었다. 

마무리
이 글은 TTGO WiFi Bluetooth ESP32 개발 방법 및 사용기를 간단히 정리해 보았다. 이 모듈은 센서, OLED 디스플레이, WiFi, Bluetooth 등이 모두 통합되어 있어, 관련 기능이 필요할 때 매우 편리하게 개발할 수 있다. 가격도 몇 달러밖에 되지 않아, 사용에 부담이 없다. 다만, 개발 시 자료가 부족하고, 응용 사례가 많지 않은 것이 단점이다. 잘 활용한다면, 저렴한 가격에 괜찬은 IoT 장치를 개발할 수 있을 것이다.

레퍼런스

TTGO WiFi Bluetooth Battery Module 18650 ESP32 0.96 inch OLED Development Tools
TTGO ESP32 OLED DEVELOPMENT TOOL
TTGO Weather station
PlatformIO.org and getting started
ThingPlus OLED SSD1306
ESP32 OLED SSD1306
A fatal error occurred: Timed out waiting for packet content - problem after writing to SPIFFS memory of ESP32

2021년 1월 20일 수요일

Arduino Nano 33 BLE보드와 TinyML 기반 딥러닝 처리 방법 및 사용기

이 글은 Arduino Nano 33 BLE 보드와 TinyML 기반 딥러닝 활용 방법에 대한 글이다. 

이 아두이노 마이크로 컨트롤러는 20달러로 저가 단일칩 독립형 컴퓨터이다. 웨어러블, 드론, 3D 프린터, 장난감, 스마트 플러그, 전기 스쿠터, 세탁기와 같은 장치에 내장된 컴퓨터이다. 이러한 장치를 인터넷으로 연결하면, 사물 인터넷이된다.

아두이노 커뮤니티는 TensorFlow Lite Micro를 새롭게 개발된 Arduino Nano 33 BLE Sense 보드에 도입했다. 이를 사용하면, 다양한 딥러닝 기계학습 어플리케이션을 손가락만한 아두이노 임베디드 보드에서 실행할 수 있다. 

아두이노에 사용하는 보드는 64MHz에서 실행되는 Arm Cortex-M4 마이크로 컨트롤러가 있으며 1MB 플래시 메모리와 256KB RAM이 있다. Arduino Nano 33 BLE Sense 보드는 손가락 크기보다 작다. 참고로, 임베디드 보드 개발시 다음과 같은 문제들로 데이터가 제대로 취득되지 않을 수 있다. 임베디드는 일반 컴퓨터보다 매우 민감하게 작동된다는 점을 고려해야 한다.

  • 소모 전류량 부족: 너무 많은 장치를 연결하지 않는다. 별도 전원을 준비한다.
  • 보드 불량(가끔식 발생함)
  • 회로 연결 오류: 테스터기로 확인해야 함
  • 불완전한 센서 문제: 센서 읽기에 지연, 인터럽트 사용, 보드 강제 리셋 등이 필요할 수 있음
  • 센서 간 충돌: 보드 내 조도 센서는 IMU등 다른 센서와 충돌이 있음. 테스트 필요함
  • 칩 자체 발열로 인한 센서값 오프셋: 캘리브레이션 처리가 필요하거나, 발열을 피할 수 있는 조건을 찾아야 함

이 부분은 아두이노 나노에 대한 많은 리포트에서 확인할 수 있다. 제대로 작동하지 않은 경우, 상세 내용은 다음 링크를 참고한다.

이 글은 아두이노 나노 33 센스 보드를 이용한 딥러닝 처리 방법을 간단히 이야기한다.

아두이노와 TinyML

기계 학습에는 신경망 모델을 마이크로 컨트롤러와 같은 메모리 제약있는 장치에서 실행할 때 사용할 수 있는 기술이 있다. 핵심 단계 중 하나는 부동 소수점을 8 비트 정수로 변환해 양자화하는 것이다. 이를 통해 딥러닝 계산을 더 빠르게 실행할 수 있다. 이런 임베디드 컴퓨터에서 기계학습(ML. Machine Learning) 처리하는 방법 중 하나가 TinyML이다. TinyML은 텐서플로우로 학습된 모델을 경량화해, 메모리 크기가 작은 아두이노 같은 소형 임베디드 컴퓨터에서 실행할 수 있도록 도와준다.

TinyML은 떠오르는 분야이다. 수십억 개의 마이크로 컨트롤러가 모든 종류의 장소에서 다양한 센서와 결합되어, 창의적이고 가치있는 TinyML 애플리케이션을 만들 수 있다. 아래 링크를 방문하면, TinyML 커뮤니티 글, 기술, 내용 및 예제를 확인할 수 있다.

Arduino Nano 33 BLE 기능

이 글을 따라하기 위해 다음과 같은 재료가 필요하다.

프로그래밍하려면 Arduino Web Editor를 사용하거나 Arduino IDE를 설치해야 한다. 

Arduino Nano 33 BLE Sense에는 다양한 온보드 센서가 있다.

  • 음성 – 디지털 마이크
  • 모션 – 9축 IMU (가속도계, 자이로 스코프, 자력계)
  • 환경 – 온도, 습도 및 압력
  • 빛 – 밝기, 색상 및 물체 근접

아울러, Bluetooth LE 연결이 있으므로 노트북, 모바일 앱 또는 기타 BLE 주변 장치로 데이터를 보낼 수 있다.

보드 설명 영상
보드 레이아웃

좀 더 상세한 내용은 다음 링크를 참고한다.

딥러닝 예제 실행하기

이 글 예제는 원래 TensorFlow 블로그에 Sandeep Mistry, Dominic Pajak에 의해 작성되었음을 밝힌다. 이 개발자들은 음성인식, 모션 동작 인식, 카메라 비전 사람 인식 예제를 워크샵했다. 

  • micro_speech : Yes, No 음성 인식
  • magic_wand: 동작 인식
  • person_detection: 사람 인식

딥러닝 음성 인식

첫번째 예제는 간단한 음성 명령 인식 신경망 모델을 아두이노에 업로드할 것이다. 이를 위해, 먼저 아두이노 IDE를 실행하고, 다음과 같이 Arduino Nano 33 BLE 보드와 라이브러리를 설치한다.

아두이노IDE의 도구>보드 매니저 메뉴를 실행해 다음과 같이 BLE 보드를 검색하고 설치한다.

Arduino Nano 33 BLE 보드 설치

보드를 설치한 후, Arduino 보드를 노트북과 연결한다. 그리고, IDE에서 보드와 COM 포트를 선택한다. 
USB 포트 연결
Arduino Nano 33 BLE 보드 및 포트 선택

이제, 스케치>라이브러리 매니저 메뉴를 선택해, Arduino Tensorflow Lite 를 검색해 라이브러리를 설치한다.

라이브러리 설치 후 파일>예제 메뉴에 Arduino Tensorflow 예제 중 micro_speech 예제를 선택하고, 업로드 한다. 아마, 소스를 컴파일하고 보드에 업로드하는 데 시간이 몇분 걸릴것이다.
업로드 중 모습
업로드 성공 모습

이제 툴>시리얼 모니터 메뉴를 실행한다. 그리고, 아두이노 보드를 입에 가까이 대고, Yes, No 단어를 말해보자. 그럼, 다음과 같이 음성을 인식해 Yes, No 텍스트를 출력해 준다. 

음성 딥러닝 모델 실행 모습

동작 제스쳐 인식

이 예제 실행을 위해, Arduino_LSM9DS1 라이브러리를 검색해 설치한다. 파일>예제>Arduino_TensorflowLite 예제에서 magic_wand 를 선택한다. 소스코드가 열리면, 다음과 같이 업로드한다.


성공적으로 업로드되었다면, 다음과 같이, 나노 보드를 흔들어보자. 그럼, 제스쳐에 따라, O, W와 같은 형태가 시리얼 모니터에 출력될 것이다.
제스쳐 인식 결과
제스쳐 실행 예시

사람 인식
이 예제는 ArduCam 카메라가 준비되어야 한다. 
ArduCam (구매)

카메라와 보드간 회로는 다음과 같이 연결한다.
회로 연결 모습(참고)

사람 인식 예제 실행을 위해, 파일>예제>Arduino_TensorflowLite>person_detection을 선택한다. 앞에서 한것처럼, 메뉴에서 업로드 버튼을 클릭한다. 그럼, 사람 인식 딥러닝 모델이 보드에서 실행되어, 다음과 같이 사람을 인식할 수 있다.
person detection 실행 결과

Nano 33과 배터리 연결하는 방법은 다음 자료를 참고하길 바란다.

IMU 센서 데이터 획득

보드에 내장된 IMU 자세 센서를 사용해 그 데이터값을 얻어본다. 
파일>예제>Arduino_LSM9DS1>SimpleGyroscope파일을 열고, 업로드한다. 
다음과 같이 실행되면 성공한 것이다.

OLED 디스플레이 연결

이 나노 보드에는 OLED 디스플레이가 없다. 그러므로, SSD1306 으로 불리는 OLED 디스플레이를 연결할 경우가 가끔 생긴다. 

나노 보드와 연결은 다음과 같이 한다.


아두이노 IDE에서 adafruit_SSD1306 라이브러리를 설치한다.
그리고, 다음과 같은 소스 코드를 업로드해 본다. 

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

#define OLED_RESET  -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define NUMFLAKES     10 // Number of snowflakes in the animation example

#define LOGO_HEIGHT   16
#define LOGO_WIDTH    16
static const unsigned char PROGMEM logo_bmp[] =
{ B00000000, B11000000,
  B00000001, B11000000,
  B00000001, B11000000,
  B00000011, B11100000,
  B11110011, B11100000,
  B11111110, B11111000,
  B01111110, B11111111,
  B00110011, B10011111,
  B00011111, B11111100,
  B00001101, B01110000,
  B00011011, B10100000,
  B00111111, B11100000,
  B00111111, B11110000,
  B01111100, B11110000,
  B01110000, B01110000,
  B00000000, B00110000 };

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

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

  // Show initial display buffer contents on the screen --
  // the library initializes this with an Adafruit splash screen.
  display.display();
  delay(2000); // Pause for 2 seconds

  // Clear the buffer
  display.clearDisplay();

  // Draw a single pixel in white
  display.drawPixel(10, 10, SSD1306_WHITE);

  // Show the display buffer on the screen. You MUST call display() after
  // drawing commands to make them visible on screen!
  display.display();
  delay(2000);
  // display.display() is NOT necessary after every single drawing command,
  // unless that's what you want...rather, you can batch up a bunch of
  // drawing operations and then update the screen all at once by calling
  // display.display(). These examples demonstrate both approaches...

  testdrawline();      // Draw many lines
  testscrolltext();    // Draw scrolling text
  testdrawbitmap(); 
}

void loop() {
}

void testdrawline() {
  int16_t i;

  display.clearDisplay(); // Clear display buffer

  for(i=0; i<display.width(); i+=4) {
    display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE);
    display.display(); // Update screen with each newly-drawn line
    delay(1);
  }
  for(i=0; i<display.height(); i+=4) {
    display.drawLine(0, 0, display.width()-1, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);
}

void testscrolltext(void) {
  display.clearDisplay();

  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(10, 0);
  display.println(F("scroll"));
  display.display();      // Show initial text
  delay(100);

  // Scroll in various directions, pausing in-between:
  display.startscrollright(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrollleft(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrolldiagright(0x00, 0x07);
  delay(2000);
  display.startscrolldiagleft(0x00, 0x07);
  delay(2000);
  display.stopscroll();
  delay(1000);
}

void testdrawbitmap(void) {
  display.clearDisplay();

  display.drawBitmap(
    (display.width()  - LOGO_WIDTH ) / 2,
    (display.height() - LOGO_HEIGHT) / 2,
    logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
  display.display();
  delay(1000);
}

OLED display가 동작하면 성공한 것이다. 

나노 BLE 모듈 센서 통합 테스트

앞서 정리한 내용을 응용해, 나노에 장착된 자이로센서, 가속도센서, 중력센서, 온습도 센서 등을 모두 테스트해 본다. 코드는 다음 깃허브에서 다운로드한다. 

업로드 컴파일 중 발생되는 라이브러리 헤더 에러는 앞서 설명한 대로 아두이노 라이브러리 검색 및 추가 기능으로 해결한다.

결과는 다음과 같다. 

이제, 이 나노 보드를 센싱할 건축 공간이나 부재에 부착하고, 데이터를 모아,유무선 통신으로 클라우드 플랫폼에 업로드하면, 데이터 분석을 할 수 있다. 

결론

이 글은 아두이노 나노 33 센스를 통해 TinyML을 간단히 사용해보고, 그 잠재력을 확인해 보았다. 실제 사용해 보면 알겠지만, 아직은 속도나 정확도가 그리 만족스럽지는 못하다. 다만, 손가락 크기의 보드에서 딥러닝 모델을 처리하고, 처리 데이터 결과를 클라우드 플랫폼에 전달할 수 있는 가능성이 많은 상상을 하게 만든다. 

TinyML은 응용목적에 따라 모델을 적절히 최적화한다면, 좀 더 나은 성능을 기대할 수 있을 것이다. 앞으로, 임베디드 보드를 이용한 딥러닝 처리는 더욱 보편화될 것이라 생각한다. 이 글을 통해, 관련 기술 개발 및 응용에 조금이나마 도움이 되었으면 한다.

레퍼런스






2020년 3월 2일 월요일

아두이노 센서 데이터의 빅데이터 처리 개발 방법

이 글은 아두이노 센서 데이터의 빅데이터 처리 개발 방법을 간단히 소개한다.

시스템 아키텍처(Gabriel, 2017, hackster.io)
제플린 노트북 빅데이터 K-means 분석 결과(Gabriel, 2017, hackster.io)
온습도 분포 분석 결과(Gabriel, 2017, hackster.io)

이 사례는 아두이노 우노, ESP8266, DHT11 온습도 센서를 사용해 데이터를 취득하여, 카프카(kafka) 서버로 발행하고, Hive 데이터 저장소에 저장된 후, Zeppelin에서 스파크(Spark) 코드를 실행해 빅데이터 분석을 수행한다.
사용된 온습도 센서 회로

분석된 빅데이터 결과는 MongoDB, Cassandra DB등을 사용해 저장한다.

레퍼런스
아두이노나 NodeMCU 센서 데이터를 MongoDB에 저장하는 예시는 다음을 참고한다.

2019년 9월 8일 일요일

우분투 node-red 설치하기

node-red는 IoT connection 미들웨어로 IBM에서 개발한 오픈소스이다. 우분투에서 설치하는 과정을 남긴다.

다음과 같이 nodejs를 설치한다.
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install -y nodejs

버전을 확인한다.
node -v

npm 명령으로 node-red 를 설치한다.
sudo npm install -g --unsafe-perm node-red

node-red를 실행한다.
node-red

다음과 같이 서버 주소를 크롬에 입력하면 노드레드 실행 모습을 확인할 수 있다.

좀 더 자세한 내용은 이 링크를 참고한다.

2019년 5월 26일 일요일

Google Cloud IoT 사용하기

이 글은 Google Cloud IoT 사용하는 방법에 대한 레퍼런스를 요약한 것이다.


레퍼런스
IoT - Using Cloud IoT Core to connect a microcontroller (ESP32) to the Google Cloud Platform
Build an IoT application with Google Cloud 

NodeMCU와 구글 스프레드시트 연결

이 글은 NodeMCU ESP8266과 구글 스프레드시트 간의 연결 방법에 대한 글을 소개한다.
튜토리얼 영상

NodeMCU 회로 구성
NodeMCU를 이용해 다음과 같이 회로를 구성한다. 센서 역할을 하는 가변저항을 연결한다. 

스프레드시트 연결
구글 스프레드시트를 만들고, 도구메뉴 스크립트 편집기에서 다음과 같이 스크립트를 추가한다.
function doGet(e) 
{
  var mo = e.parameter.func;
  if(mo == "addData")
  {
    var stat = add_data(e);
    if(stat == 1)
    {
      var result = 
      {
        status : true
      };
      return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JSON);
    }
  }
}
function add_data(e)
{
  var sheet = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/182EnOR4vF5eVs4wGD-zOn7pKy_6BMpED8ApjIGh0C9Q/edit#gid=0');
  var lastVal = sheet.getRange("A1:A").getValues();
  var id = lastVal.filter(String).lenght;

  var CurrentDate = new Date();
  var Date_ = Utilities.formatDate(CurrentDate, "IST", "dd/MM/YYYY");
  var Time_ = Utilities.formatDate(CurrentDate, "IST", "HH:mm:ss");

  sheet.appendRow([id, Date_, Time_, e.parameter.val]);
  return 1;
}
게시>웹 앱으로 배포 메뉴를 실행하고, 모두 접근 가능한 권한으로 배포한다.

NodeMCU 코딩
NodeMCU에 다음과 같이 코딩한다. 단, 코드에서 url 은 앞서 배포된 웹 앱 링크 주소로 변경해야 한다.  
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>

const char *ssid = "SERVER NAME"; 
const char *password = "SERVER PASSWORD";  
const char* host = "script.google.com"; 
const char* fingerprint = "89 ff f4 0f 4d 98 09 ed e3 ef 95 f2 8a af af 22 89 08 ac 03";
String url;

void setup() 
{
  Serial.begin(115200);
  delay(100);
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.begin(ssid, password); 
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(500);
    Serial.print(".");
  }
 
  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.print("Netmask: ");
  Serial.println(WiFi.subnetMask());
  Serial.print("Gateway: ");
  Serial.println(WiFi.gatewayIP());
}

void loop() 
{
  Serial.print("connecting to ");
  Serial.println(host);
 
  WiFiClientSecure client;

  const int httpPort = 443;
  if (!client.connect(host, httpPort)) 
  {
    Serial.println("connection failed");
    return;
  }

  float t = analogRead(A0);
  
  url = "/macros/s/AKfycbyvGjcryd7c5uNeX6dkleZhmjDKyTrs1L9Lf3kWlPhTZDn9JPrH/exec?func=addData&val="+ String(t);
  Serial.print("Requesting URL: ");
  Serial.println(url);
  
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
  delay(500);
  String section="header";
  while(client.available())
  {
    String line = client.readStringUntil('\r');
    Serial.print(line);
  }
  Serial.println();
  Serial.println("closing connection");
  delay(6000);
}
코드를 업로드하여 실행하면, 약 6초마다 NodeMCU에서 읽은 데이터가 스프레드시트에 업데이트되는 것을 확인할 수 있다.

레퍼런스

2019년 5월 23일 목요일

IoT 커넥션 오픈소스 NODE-RED 사용법 - node-red + NodeMCU + MQTT

이 글은 IoT 장치들간 연결에 사용되는 오픈소스인 노드레드(NODE-RED)를 사용하는 방법을 간단히 나눔한다. 이 글은 IoT 구현을 위해 노드레드, NodeMCU를 사용한다.

노드레드는 IBM에서 IoT 시스템 개발 지원하는 오픈소스 플랫폼이다. 노드레드를 이용하면, 코딩할 필요없이 다양한 IoT 프로토콜, 입출력 연결을 손쉽게 처리할 수 있다. 노드레드는 아파치 라이센스 2.0을 지원하기 때문에 라이센스 규약만 지키면 상용 패키지를 개발하는 데 큰 문제가 없다.

이 글은 노드레드를 이용해 다음과 같이 IoT 장치와 MQTT방식으로 데이터 교환을 하는 간단한 IoT 시작품 만드는 방법을 보여준다.
노드레드로 만든 간단한 IoT 데쉬보드 테스트
nodered.org 소개

노드레드 설치
설치는 간단하다.

1. Node.js 설치
노드 레드는 노드JS를 사용한다. 우선 아래 링크에서 Node.js LTS 버전을 다운로드 받아 설치한다.

2. Node.js 명령 콘솔 실행 및 버전 확인
다음과 같이 설치된 메뉴 중에 command prompt 메뉴를 실행한다.
실행 후, 다음 명령어로 노드JS 설치 버전을 확인한다.
node --version; npm --version

3. node-red 및 데쉬보드 설치
다음 명령어로 node-red와 데쉬보드를 설치한다. 참고로, node-red는 데쉬보드와 같이 다양한 추가 플러그인을 지원한다.
npm install -g node-red
npm i node-red-dashboard

4. node-red 실행
다음 명령으로 node-red를 실행한다. 만약, network security error (PPSecurityException)발생하면 Set-ExecutionPolicy -ExecutionPolicy RemoteSigned 명령을 터미널에서 실행한다.
node-red

5. node-red 웹브라우저 실행
크롬을 실행한 후 http://127.0.0.1:1880/ 에 접속하면, node-red GUI를 확인할 수 있다. 

노드레드 사용
IoT 시스템 디자인
우리는 MQTT란 IoT 표준 프로토콜을 이용해, NodeMCU 에서 얻은 센서값을 노드레드에 전달해 줄 것이다. 이를 위해, MQTT 데이터를 저장하고 있어야 할 MQTT 브로커가 있어야 한다. 브로커는 http://test.mosquitto.org 란 오픈소스 서버를 사용하기로 한다. 이 서버는 공개이며 무료로 사용할 수 있다.

아울러, 노드레드에서 NodeMCU로 MQTT 데이터를 전달하는 예제도 구현할 것이다. NodeMCU에 전달할 데이터는 단순히 NodeMCU에 연결된 LED를 켜고 끄는 데 사용한다. 

참고로, 센서값과 LED ON/OFF는 노드레드에서 제공하는 데쉬보드를 이용해 GUI를 쉽게 구현할 수 있다. 

NodeMCU 회로 구성 및 코딩
1. 회로구성
다음과 같이 NodeMCU 회로를 구성한다.


   D4 PIN = LED +
   GND PIN = LED -
   GND PIN = 10K 저항 끝단
   A0 PIN = 10K 저항 반대 끝단
   A0 PIN = 조도센서 끝단
   3.3V PIN = 조도센서 반대 끝단

참고로, NodeMCU 핀번호는 다음과 같다. 

2. 코딩
컴퓨터와 NodeMCU를 USB케이블로 연결한다. 그리고, 아두이노 IDE를 실행하고, 툴>보드 메뉴에서 NodeMCU 1.0을 선택하고, 툴>포트 메뉴에서 NodeMCU와 연결된 포트를 선택한다.

다음 코드를 붙여넣고, 코드에서 WiFi ssid와 pwd를 수정한 후, NodeMCU 보드에 업로드한다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char* mqtt_server="test.mosquitto.org";
WiFiClient espclient;

void callback(char* topic,byte* payload,unsigned int length1){    
  Serial.print("message arrived[");
  Serial.print(topic);
  Serial.println("]");
  
  String data = "";
  for(int i=0;i<length1;i++)
    data = data + payload[i];     
  Serial.println(data);
  Serial.println(payload[0]);

  if(payload[0] == 48)      // if(data == "48")
  {
    digitalWrite(D4, LOW);  //ASCII VALUE OF '0' IS 48
    Serial.println("off");
  }
  else if(payload[0] == 49) // else if(data == "49")
  {
    digitalWrite(D4, HIGH);   //ASCII VALUE OF '1' IS 49
    Serial.println("on");
  }
}

PubSubClient client(mqtt_server,1883,callback,espclient);

void setup() {
  pinMode(D2,OUTPUT);
  Serial.begin(115200);
  Serial.print("connecting");
  WiFi.begin("ssid","pwd");         //SSID,PASSWORD 
  while(WiFi.status()!=WL_CONNECTED){
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  digitalWrite(LED_BUILTIN, HIGH); 
  
  reconnect();
}

void reconnect(){
  while(WiFi.status()!=WL_CONNECTED){
    delay(500);
    Serial.print(".");
  }
  while(!client.connected()){
    if(client.connect("ESP8266Client123456789")){
      Serial.println("connected");
      client.subscribe("ledcontrol");
    }
    else{
      Serial.print("failed,rc=");
      Serial.println(client.state());
      delay(500);
    }
  } 
}

int now = 0;
int lastMeasure = 0;

void loop() {
  if(!client.connected()){
    reconnect();
  }
  
  client.loop();

  // Timer variable with current time
  now = millis();
  if (now - lastMeasure > 3000) {
    lastMeasure = now;
    int value = analogRead(A0);
    String data = String(value);
    client.publish("sensor/light", data.c_str());  
  }
}

노드레드 디자인
1. MQTT 노드 설정과 LED ON/OFF 버튼 생성
우선, 노드레드의 입력>mqtt 를 Drag&drop으로 생성한다. 생성된 mqtt노드를 더블클릭해, 다음과 같은 속성창에서 http://test.mosquitto.org 서버(포트 = 1883) 추가하고, 토픽명은 ledcontrol, QoS=0 으로 설정한다.

버튼을 2개 추가하고, 속성을 다음과 같이 각각 설정한다. 참고로, Group에 설정된 값은 데쉬보드에 함께 표시되는 그룹을 결정한다.
LED ON 버튼 설정

LED OFF 버튼 설정

방금 만든 MQTT와 버튼 2개를 다음과 같이 연결한다.

2. 조도센서 MQTT 노드 생성과 데이터 확인용 debug 생성
MQTT노드를 하나 더 추가하고, 아래와 같이 토픽=sensor/light 로 설정한다. 

데쉬보드에서 debug를 만들고, mqtt와 서로 연결한다.

debug의 속성은 다음과 같이 설정한다.

3. 조도센서 MQTT 노드 생성과 데이터 확인용 guage 생성
방금 만든 mqtt (sensor/light)를 복사해 붙여넣어 하나 더 만든다. 
그리고, 데쉬보드에서 다음과 같이 gauge를 만든 후 서로 연결한다.

gauge의 속성은 다음과 같이 설정한다.

이렇게까지 하면, 다음과 같이 노드레드가 구성되었을 것이다. 

데쉬보드 Layout 탭을 선택해 다음과 같이 탭, 그룹을 디자인한다. 다음과 같이 on, off, gauge를 정의한다.

4. 노드레드 설정 배포 및 데쉬보드 확인
이제 배포하기를 클릭한다. 그리고 디버그 탭을 선택한다. 다음과 같이 NodeMCU에서 MQTT로 전달받은 데이터가 로그로 출력되고 있을 것이다. 

Layout 탭의 화살표 아이콘을 클릭하면 데쉬보드가 다음과 같이 실행된다. 

ON/OFF 버튼을 클릭해 보자. 몇초후에 NodeMCU 에 연결된 LED가 동작할 것이다.

차트도 다음과 같이 추가해 mqtt와 연결해 보자. 

다시 배포한 후 데쉬보드를 확인하면, 다음과 같이 차트가 추가된 것을 확인할 수 있다.
노드레드 데쉬보드 결과

만약 좀 더 좋은 사용자 인터페이스가 필요하다면 그라파나(grafana)를 사용할 수도 있다. 참고로, 그라파나는 코딩하지 않고 데이터 소스를 연결해 시각화하는 모니터링 도구로 아파치 라이센스 2.0을 준수하고 있다.

마무리
앞에서 IoT 데이터를 NodeMCU로 부터 MQTT 프로토콜로 받아 데쉬보드로 확인하는 것까지 해 보았다. 노드레드로 하지 않았다면, MQTT 코딩부터 데쉬보드 구현까지 많은 시간이 걸렸을 것이다. 이 과정은 코딩이 불필요하며, 익숙해 지면 몇십분만에 끝낼 수 있다.

노드레드는 오픈소스로 자기 컴퓨터를 서버로 운영하여 데이터를 저장할 수 있으고, 메일, 트위터, MQTT 등 다양한 입출력 유형을 제공하여 가성비가 매우 좋다. 데쉬보드는 N-screen을 지원하여, 크롬, 스마트폰 등을 모두 지원한다.

레퍼런스