41일 동안 들리지 않던 위성의 목소리
Request edit accessWhen the owner approves, you get an invite link and code by email.

5월 21일 새벽 3시 12분, 노트북 화면 속 파란 폭포에서 초록색 줄이 사라졌다. 그게 여울-1의 마지막 신호였다. 아니, 마지막이라고 우리는 41일 동안 믿었다.
손바닥만 한 위성
여울-1은 가로·세로·높이 10 cm, 무게 1.18 kg인 1U 큐브위성이다. 동아리 11명이 3년 동안 만들었고, 2026년 5월 12일 고도 520 km 태양동기궤도에 올라갔다. 하는 일은 하나, 궤도를 돌며 우리 학교 이름을 9600 bps 신호로 지구에 보내는 것.
숫자 카운트업
이 글에 나오는 말
위성은 비컨[1]위성이 정해진 간격으로 "나 살아 있어" 하고 보내는 짧은 신호.을 보내고, 지상국은 도플러[2]위성이 다가오면 주파수가 높아지고 멀어지면 낮아지는 현상. 한 번 지나갈 때 약 ±10 kHz 흔들린다.로 흔들리는 주파수를 따라가며, 위성 안의 와치독[3]컴퓨터가 일정 시간 응답이 없으면 강제로 다시 시작시키는 타이머.은 멈춘 컴퓨터를 다시 켠다.
- 비컨: 위성이 정해진 간격으로 "나 살아 있어" 하고 보내는 짧은 신호.
- 도플러: 위성이 다가오면 주파수가 높아지고 멀어지면 낮아지는 현상. 한 번 지나갈 때 약 ±10 kHz 흔들린다.
- 와치독: 컴퓨터가 일정 시간 응답이 없으면 강제로 다시 시작시키는 타이머.
9일째 새벽, 신호가 끊겼다
처음 8일은 순조로웠다. 서울 상공을 지나는 하루 4~6번의 기회마다 학교 옥상 안테나로 비컨을 받았다. 그런데 배터리 전압이 매일 조금씩 내려가고 있었다.
| 항목 | 배터리 |
|---|---|
| D1 | 4.02V |
| D2 | 3.98V |
| D3 | 3.93V |
| D4 | 3.87V |
| D5 | 3.81V |
| D6 | 3.74V |
| D7 | 3.66V |
| D8 | 3.58V |
| D9 | 3.49V |
9일째 새벽 패스에서 신호가 3분 만에 끊겼다. 다음 패스에도, 그다음 날에도 들리지 않았다. 옥상에 앉아 노트북만 보던 날이 이어졌다.
41일 동안 들은 것
우리는 포기하지 않았다. 41일 동안 서울 위를 지나간 패스 203번을 하나도 빠뜨리지 않고 녹음했고, 23개 나라 51곳의 아마추어 무선국에 "들리면 알려 달라"고 메일을 보냈다.
| 단계 | 값 | 이전 단계 대비 전환율 |
|---|---|---|
| 녹음한 패스 | 203 | — |
| 잡음 위에 뭔가 보인 패스 | 38 | 18.72% |
| 위성 궤도와 도플러가 맞은 패스 | 11 | 28.95% |
| 해독된 패스 | 0 | 0% |
칠레에서 온 메일 한 통
42일째 아침, 칠레 푼타아레나스의 무선사 마르타 비달에게서 메일이 왔다. 첨부한 폭포 화면에 가느다란 초록 줄이 비스듬히 그어져 있었다. 제목은 "Is this yours? It is beeping."
"삐 소리가 너무 규칙적이라 사람이 보내는 것 같지 않았어요. 그래서 궤도표를 찾아봤죠." - 마르타 비달
그날 밤 우리는 지난 41일 동안 녹음한 파일을 전부 모스 부호로 다시 돌렸다. 해독기는 40줄짜리 파이썬이었다.
# 여울-1 안전 모드 비컨: 0.1 W 모스 부호 해독import numpy as npdef cw_envelope(iq, rate, tone_hz, win=0.02): t = np.arange(len(iq)) / rate mixed = iq * np.exp(-2j * np.pi * tone_hz * t) # 도플러로 흔들리는 톤을 0 Hz로 n = int(win * rate) return np.convolve(np.abs(mixed), np.ones(n) / n, "same")def to_morse(env, rate, wpm=12): dot = 1.2 / wpm # 12 WPM이면 점 하나 0.1초 on = env > np.percentile(env, 80) * 0.5 edges = np.flatnonzero(np.diff(on.astype(int))) + 1 runs = np.diff(np.r_[0, edges, len(on)]) / rate return "".join("." if r < 2 * dot else "-" for r, o in zip(runs, on[np.r_[0, edges]]) if o)위성은 하루 45번 재부팅하고 있었다
해독된 첫 문장은 "YEOUL1 SAFE BAT 3.41 RST 1847"이었다. 배터리 3.41 V, 그리고 재부팅 1,847번. 41일 동안 하루 약 45번, 거의 한 바퀴에 한 번씩 꺼졌다 켜진 셈이다.
| 순서 | 단계 | 설명 |
|---|---|---|
| 1 | 지구 그림자 진입 | 배터리 히터가 켜진다 |
| 2 | 전압 급강하 | 3.3 V 아래로 순간 하락 |
| 3 | 와치독 재부팅 | 컴퓨터가 멈췄다고 판단 |
| 4 | 햇빛 구간 충전 | 다시 안전 모드로 깨어남 |
| 항목 | 태양전지 충전 | 히터 소모 |
|---|---|---|
| 0 | 1.9W | 0W |
| 10 | 2.1W | 0W |
| 20 | 2.2W | 0W |
| 30 | 2.2W | 0W |
| 40 | 2.1W | 0W |
| 50 | 1.9W | 0W |
| 60 | 0W | 1.6W |
| 70 | 0W | 1.6W |
| 80 | 0W | 1.6W |
| 90 | 0W | 1.6W |
명령 하나를 올리기까지
원인은 히터였다. 해결책도 단순했다. 그림자 구간에서 히터를 끄는 명령 하나. 문제는 위성이 안전 모드에서 명령을 받을 수 있는 시간이 한 패스에 40초뿐이라는 것.
복구 순서
다시 처음부터 만든다면
안전 모드 신호를 왜 그렇게 정했나요?
모스 부호는 아주 약해도 사람 귀로 들린다. 그 판단은 맞았다. 틀린 건 우리가 그걸 들을 준비를 안 한 것.
다음 위성에서 바꿀 것은?
히터는 배터리가 3.6 V 이상일 때만 켠다.
안전 모드 비컨 해독기를 처음부터 지상국에 함께 켜 둔다.
마르타는 지금 뭐 하나요?
여울-2 지상국 협력 명단 첫 줄에 이름을 올렸다. 동아리방에는 푼타아레나스 엽서가 붙어 있다.
41일 동안 우리가 들은 건 잡음이 아니었다. 위성은 내내 말하고 있었고, 우리가 다른 언어로 듣고 있었을 뿐이다. 다음에는 처음부터 귀를 하나 더 열어 둘 생각이다.

