← 전체 포스팅

[스마트 굴비] DIY IoT Matter 조명 - 완성

메인보드 테스트 #

지난 포스팅에서 조립한 메인보드를 테스트합니다. nRF54L15 SoC와 모듈인 ME54BS01이 처음이다 보니 상당히 긴장되었습니다.

LED 테스트 #

우선 펌웨어는 잘 올라가는지, LED 드라이버 모스펫은 작동하는지 확인했습니다. 잘 작동하는 모습입니다. 다행이네요.

Matter NFC 커미셔닝 테스트 #

nRF52840 디버거로 스마트 굴비 Matter 메인보드를 테스트하는 모습

가지고 있던 nRF54L15 DK의 J-Link OB SWD 커넥터와 맞는 게 없어서 CMSIS-DAP 어댑터로 어찌어찌 해 보려 했는데요, RTT 맛을 봐 버리니 돌아가지를 못하겠더라고요. nRF52840을 구해 와서 SWD를 뽑아 지그에 꽂고 마저 테스트했습니다.

별 기대 없이 수틀리면 메모리 밀어 버려야지(?) 하던 NFC가 안테나를 꽂았다고 바로 작동합니다. 세상에.. 와.. 이거 너무 신기하네요 ㅋㅋ QR 코드 찾을 필요도, 메모해 둘 필요도 없이 가져다 대면 끝!! 이게 진짜 21세기죠 👍

Home Assistant에 연결해 마저 조명을 테스트합니다.

Home Assistant에 연결된 스마트 굴비 조명
Home Assistant에서 밝기를 7%로 낮춘 스마트 굴비 Matter 조명
Home Assistant에서 밝기를 100%로 높인 스마트 굴비 Matter 조명
Home Assistant에서 차가운 색온도로 설정한 스마트 굴비 Matter 조명
Home Assistant에서 따뜻한 색온도로 설정한 스마트 굴비 Matter 조명

기능 추가 #

지난 1편에서의 펌웨어도 사용에는 큰 문제가 없지만, 조금 욕심을 내어 몇몇 기능을 추가했습니다.

전원 토글 디커미셔닝 #

전등처럼 버튼을 누르기 어려운 기기는 전원을 n번 토글해서 리셋하는 기능을 제공하는데요, 이것과 동일한 기능을 구현해 봤습니다.

c
// 포스팅을 위해 리턴값 체크 삭제, 상수 하드코딩
static void s_reset_count(struct k_work *work) {
  settings_delete("boot_detector/count");
}

bool boot_detector_init(void) {
  settings_subsys_init();
  settings_load_one("boot_detector/count",
                    &s_boot_count,
                    sizeof(s_boot_count));

  if (s_boot_count < UINT8_MAX) {
    s_boot_count++;
  }

  settings_save_one("boot_detector/count",
                    &s_boot_count,
                    sizeof(s_boot_count));

  s_triggered = s_boot_count >= 3U;
  if (s_triggered) {
    if (!s_clear_count()) {
      s_triggered = false;
      return false;
    }
    return true;
  }

  k_work_init_delayable(&s_reset_work, s_reset_count);
  k_work_schedule(&s_reset_work, K_SECONDS(5));

  return true;
}

Zephyr RTOS의 Settings를 사용해 설정을 저장한 뒤, 3번 반복했다면 s_triggered flag를 켜서 디커미셔닝에 활용하도록 했습니다. 한편, 전원을 켠 뒤 5초가 지나면 카운트를 초기화하도록 했습니다.

디커미셔닝할 때에는 빠르게 깜박이는 효과를 줬습니다. 효과가 발생하는 도중에 전원을 끄면 디커미셔닝이 취소됩니다.

온도 센서 #

c
double temperature_get(void) {
  struct sensor_value val;
  int ret = sensor_sample_fetch(s_dev);

  if (ret != 0) {
    LOG_WRN("Failed to fetch sample (ret: %d)", ret);
    return -1.0;
  }

  ret = sensor_channel_get(s_dev, SENSOR_CHAN_DIE_TEMP, &val);
  if (ret != 0) {
    LOG_WRN("Failed to get temperature (ret: %d)", ret);
    return -1.0;
  }

  return sensor_value_to_double(&val);
}

Zephyr 자료를 찾던 중에 SoC에서 온도 센서를 지원한다는 것을 알게 되어 간단히 추가해 봤습니다.

ZAP GUI에서 Matter 조명에 온도 측정 클러스터를 추가한 화면
ZAP GUI의 Matter Temperature Measurement 클러스터 설정 화면

zap-gui에서 Endpoint를 추가하고,

c
extern "C" matter_c_err_t matter_c_set_temperature(double temperature) {
  const int16_t value = static_cast<int16_t>(temperature * 100.0);

  CHIP_ERROR err = SystemLayer().ScheduleLambda([value] {
    auto status = Clusters::TemperatureMeasurement::Attributes::MeasuredValue::Set(2, value);

    if (status != Protocols::InteractionModel::Status::Success) {
      LOG_ERR("Updating temperature failed: %x", to_underlying(status));
    }
  });

  return map_error(err);
}

코드에서는 이런 식으로 온도를 업데이트합니다. Matter API(여기서는 Clusters::(생략)::Set)를 호출하는 task가 Matter의 context가 아니라면 Lambda로 던져야 한다고 합니다. 람다에서 사용하는 변수는 대괄호에 넣어서 캡처하고요. 아 그나저나 C++ 람다 부럽네요. 직전의 디커미셔닝 카운트 초기화에서 람다가 아른거리던데..

케이스 조립 및 완성 #

스마트 굴비 조명 케이스 내부에 장착한 NFC 안테나와 전원 커넥터

NFC와 전원 커넥터를 붙여 주고,

스마트 굴비 조명 케이스에 조립한 nRF54L15 Matter 메인보드

메인보드는 이렇게,

케이스 조립을 마친 DIY IoT 스마트 굴비 Matter 조명

처음과 같은 상태로 돌아갑니다. 이 굴비가 스마트한 굴비가 맞을까요?

최종 테스트 #

스마트홈 플랫폼으로 Home Assistant를 사용하고 있어, HA에 조명을 연결해 봅니다.

마무리 #

굴비 인형과 전구를 결합해 완성한 스마트 굴비 Matter 조명
뾱!

Matter!! 채신기술!!! 21세기!!!

최근 이케아에서 만 원짜리 Matter 플러그를 만들며 Matter 대중화에 스타트를 끊은 느낌입니다. 다만, Matter의 비싼 인증 비용으로 가끔 알리에서 튀어나오는 $1짜리 온도 센서!!! 이런 건 여전히 어려울 것 같습니다. 많은 분들이 여전히 Matter에 의문을 가지는 이유이기도 합니다. 저 역시 앞으로도 Zigbee를 주력으로 사용할 가능성이 높고요.

그럼에도 DIY를 할 때에는 Matter가 정말 맛있었습니다. 드디어 집을 찾은 느낌입니다.

우선 연결성 하나는 깡패입니다. Wi-Fi 기기는 AP 정보 전달부터 고민해야 하고, Home Assistant에 붙이기 위한 MQTT Discovery는 HA에 종속되게 만듭니다. Zigbee 쪽은 Z2M을 사용한다면 컨버터를 만들어야 하고요. 반면 Matter는 모든 걸 생략해 버립니다. QR, 여기서는 NFC만 찍으면 모두 알아서 합니다. 심지어 플랫폼에 종속되지 않고 애플 홈처럼 다른 스마트홈 앱에도 마음대로 연결이 가능하죠. 미인증 기기라는 경고 문구가 나오긴 하지만, 혼자 사용하는데 뭐 어떤가요.

다음으로 nRF Connect SDK의 Matter 개발 환경이 끝내줬습니다. Matter SDK의 추상화 수준도 마음에 들었고요. Zigbee 때에는 Cluster 구성을 C에서 모두 선언해야 했지만, Matter에서는 ZAP GUI에서 클릭 몇 번 하고 Generate 하면 모두 끝났습니다. Endpoint, Cluster, Attribute 구성은 물론 기본값과 RAM/NVM 저장 여부까지 GUI에서 설정할 수 있었습니다. 특히 SDK의 추상화가 꽤 잘 되어 있어서, 애플리케이션 코드에서는 초기화와 콜백만 처리해도 어지간한 기능을 구현할 수 있었습니다.

아 근데 ESPHome 왜 안 쓰냐고요..? 어... 글쎄요......

아무튼 이번 프로젝트로 정말 재미있는 경험을 했습니다. 다음에 IoT 기기를 만들 일이 생긴다면 별 고민 없이 Matter를 잡을 것 같습니다.