센서가 준비되고 무선이 뚫리자 다음 질문이 왔습니다. 몇 대까지 붙일 수 있습니까.

처음 구조는 단순했습니다. 장치가 각자 자기 타이머로 측정하고 올려 보냅니다. 만들기는 제일 쉽습니다. 그런데 이건 순수 ALOHA 입니다 — 서로 언제 말하는지 모르니 부딪히는 걸 막을 방법이 없습니다. 30대에서 충돌을 1% 아래로 누르려면 전송 주기를 5분까지 벌려야 했습니다.

5분에 한 번은 너무 느립니다. 그래서 뒤집었습니다.

장치가 알아서 말하게 두지 말고, 서버가 한 대씩 부릅니다. 부르는 쪽이 하나면 둘이 동시에 말할 일이 애초에 없습니다.

응답을 기다리면 안 되는 이유 — 다운링크 1초 스케줄러

응답을 기다리는 폴링은 부르고 → 응답을 받고 → 다음 장치를 부르는 순서로 짰습니다. 자연스러운 순서입니다. 그리고 30대에 42초가 걸렸습니다.

실측해 보니 이유가 나왔습니다.

구간시간
무선 왕복 자체466 ms
부른 뒤 응답까지1,444 ms
차이약 1초

이 1초는 전파 시간이 아닙니다. 게이트웨이가 다운링크를 1초 주기 스케줄러로 내보내기 때문에 생기는 대기입니다. 기다리는 방식에서는 이 1초가 대수만큼 그대로 쌓입니다.

그래서 응답을 안 기다리기로 했습니다. 일정 간격으로 계속 부르고, 응답은 나중에 도착하는 대로 짝을 맞춥니다. 그러면 그 1초는 모든 장치에 똑같이 얹히는 상수가 되고, 한 바퀴는 부르는 간격만으로 정해집니다.

간격을 무한정 좁힐 수는 없습니다. 응답끼리 겹치면 다시 충돌이니, 업링크 전파시간보다 넉넉히 크게 잡아야 합니다. 30대 기준 1초 간격 = 한 바퀴 30초로 정했습니다.

응답 없는 LoRa 장치는 쉬게 둡니다

응답 없는 장치 건너뛰기를 조건으로 하나 더 붙였습니다. 응답이 없는 장치를 계속 부르면 안 됩니다.

전원이 꺼졌다 켜진 장치는 게이트웨이에 다시 접속해야 하는데, 그 사이에도 계속 부르고 있으면 게이트웨이 송신기가 묶여서 접속 요청을 못 받습니다. 부를수록 늦게 돌아오는 셈입니다.

그래서 몇 번 놓친 장치는 잠시 쉬게 두고 다음으로 넘어갑니다. 대신 접속했다는 소식이 오면 그 즉시 다시 부릅니다.

다운링크 재호출 간격에도 하한이 있었습니다

게이트웨이 다운링크 슬롯의 재호출 하한은 간격을 줄여 보다가 알게 된 것입니다. 6초 간격으로 같은 장치를 다시 부르면 실패하고, 10초를 주면 통과했습니다.

문서에서 찾은 게 아니라 값을 바꿔가며 확인해서 알아낸 값입니다. 이런 것들은 대개 문서에 없고, 없다는 걸 알기까지가 더 오래 걸립니다.

MQTT 업링크 감시 창 — 지금 무슨 일이 벌어지는지

업링크 감시 창은 폴링이 도는 동안 무엇이 오가는지 보려고 만들었습니다.

업링크 모니터

수신 업링크가 시각순으로 쌓입니다. 장치·SEQ·RSSI·SNR·사유·측정값·슬레이브·CRC와 원본 페이로드까지 한 줄에 들어 있고, 오른쪽에 장치별 집계가 따로 돕니다. (장치 식별자와 서버 주소는 가렸습니다.)

이 화면이 있어서 잡은 것이 많습니다. 사유 열에 폴링 응답인지 자율 전송인지가 찍히고, 슬레이브 열로 센서 몇 번이 답했는지가 보입니다. 위 화면에서도 한 장치는 정상값을 올리고 있고 다른 장치는 센서 끊김 이 찍혀 있습니다 — 노드는 살아 있는데 그 아래 센서가 대답을 안 하는 상태입니다. 무선 문제와 센서 문제를 눈으로 갈라 볼 수 있습니다.

브로커도 직접 구현했습니다. 이 창 하나 때문에 별도 MQTT 브로커를 설치하게 만들고 싶지 않았고, 실제로 필요한 것은 접속·발행·구독·핑 넷뿐이라 그 편이 오히려 간단했습니다.

노드 설정 도구 — AT 명령을 화면으로

LoRa 노드 설정은 원래 AT 명령을 하나씩 쳐서 넣었습니다. 센서 개수, 통신 속도, 폴링 주기, 타임아웃, 그리고 게이트웨이 접속용 키까지. 현장에서 이걸 손으로 치는 건 무리입니다.

설정 도구

연결·설정·게이트웨이 접속·펌웨어 업데이트가 한 화면에 있습니다. (화면은 장치를 연결하지 않은 상태입니다.)

만들면서 배운 것이 셋 있습니다.

하나. 포트를 여는 것만으로 모듈이 재부팅됩니다. 시리얼 포트를 열면 제어선이 토글되면서 모듈이 리셋됩니다. 그래서 값을 넣고 저장까지 하지 않으면 다음 연결 때 전부 사라집니다. 이걸 모르면 “분명히 넣었는데 왜 없지”를 반복하게 됩니다.

둘. 슬레이브 번호는 설정이 아니라 발견입니다. 처음엔 “슬레이브 번호”를 사용자가 입력하게 했습니다. 그런데 현장에서 센서가 몇 번으로 잡혀 있는지는 사람이 아는 게 아니라 노드가 스캔해서 알아내는 것입니다. 그래서 입력칸을 지우고 “감지 센서(1~5)” 표시로 바꿨습니다. 사용자가 정할 수 없는 값을 물어보면 안 됩니다.

셋. 펌웨어를 굽는 데 버튼을 누를 필요가 없습니다. 원래는 모듈의 리셋 버튼을 빠르게 두 번 눌러 부트로더로 들어가야 합니다. 그런데 이 계열 칩은 특정 속도로 포트를 열었다 닫으면 부트로더로 넘어갑니다. 그 동작을 도구에 넣으니 현장에서 뚜껑을 열 일이 없어졌습니다.

게이트웨이 관리 도구 — 로그인이 안 됐던 이유

게이트웨이 API 관리 도구는 설정을 매번 웹 화면에서 클릭하는 것도 일이라 따로 만들었습니다. 그런데 로그인부터 계속 실패했습니다.

아이디도 비밀번호도 맞는데 인증 토큰을 못 꺼냈습니다. 응답을 뜯어보고 나서야 알았습니다 — 이 펌웨어는 토큰을 흔히 쓰는 이름이 아니라 자기만의 필드명으로 돌려주고 있었습니다. 저는 흔한 이름 몇 개만 찾고 있었습니다.

여기서 조심할 게 하나 있습니다. API를 더듬느라 로그인 실패가 쌓이면 게이트웨이가 잠깁니다. 남은 시도 횟수가 응답에 실려 오는데, 그걸 보고서야 “이건 조심해서 눌러야 하는 문”이라는 걸 알았습니다.

설계에서 하나만 지켰습니다. 무선 설정은 통째로 읽어서 바꿀 필드만 갈아 끼운 뒤 다시 씁니다. 그래야 이 도구가 모르는 설정까지 보존됩니다. 운영 중인 게이트웨이를 건드리는 도구라면 이건 선택이 아닙니다.

응답을 기다리지 않고 일정 간격으로 부르면 다운링크 1초 대기가 대수만큼 쌓이지 않고, 30대 한 바퀴가 42초에서 30초로 줄어듭니다.


▶️ 다음 편 — 간섭 0 mm³인데 조립이 안 됩니다: 동작하는 노드를 제품으로 만들려면 상자가 필요했습니다. 간섭검사는 계속 통과하는데 조립은 다섯 번 실패했습니다.

🔧 이전 편: 실기기 없이 센서를 만듭니다

문의