[스마트 굴비] DIY IoT Matter 조명 - 완성
메인보드 테스트 #
지난 포스팅에서 조립한 메인보드를 테스트합니다. nRF54L15 SoC와 모듈인 ME54BS01이 처음이다 보니 상당히 긴장되었습니다.
LED 테스트 #
우선 펌웨어는 잘 올라가는지, LED 드라이버 모스펫은 작동하는지 확인했습니다. 잘 작동하는 모습입니다. 다행이네요.
Matter NFC 커미셔닝 테스트 #

가지고 있던 nRF54L15 DK의 J-Link OB SWD 커넥터와 맞는 게 없어서 CMSIS-DAP 어댑터로 어찌어찌 해 보려 했는데요, RTT 맛을 봐 버리니 돌아가지를 못하겠더라고요. nRF52840을 구해 와서 SWD를 뽑아 지그에 꽂고 마저 테스트했습니다.
별 기대 없이 수틀리면 메모리 밀어 버려야지(?) 하던 NFC가 안테나를 꽂았다고 바로 작동합니다. 세상에.. 와.. 이거 너무 신기하네요 ㅋㅋ QR 코드 찾을 필요도, 메모해 둘 필요도 없이 가져다 대면 끝!! 이게 진짜 21세기죠 👍
Home Assistant에 연결해 마저 조명을 테스트합니다.





기능 추가 #
지난 1편에서의 펌웨어도 사용에는 큰 문제가 없지만, 조금 욕심을 내어 몇몇 기능을 추가했습니다.
전원 토글 디커미셔닝 #
전등처럼 버튼을 누르기 어려운 기기는 전원을 n번 토글해서 리셋하는 기능을 제공하는데요, 이것과 동일한 기능을 구현해 봤습니다.
// 포스팅을 위해 리턴값 체크 삭제, 상수 하드코딩
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초가 지나면 카운트를 초기화하도록 했습니다.
디커미셔닝할 때에는 빠르게 깜박이는 효과를 줬습니다. 효과가 발생하는 도중에 전원을 끄면 디커미셔닝이 취소됩니다.
온도 센서 #
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에서 Endpoint를 추가하고,
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와 전원 커넥터를 붙여 주고,

메인보드는 이렇게,

처음과 같은 상태로 돌아갑니다. 이 굴비가 스마트한 굴비가 맞을까요?
최종 테스트 #
스마트홈 플랫폼으로 Home Assistant를 사용하고 있어, HA에 조명을 연결해 봅니다.
마무리 #

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를 잡을 것 같습니다.