PortDock

PortDock Plot 사용법

시리얼·TCP·UDP 숫자를 실시간 그래프로

이 프로그램은

PortDock Plot 은 시리얼·TCP·UDP 로 들어오는 숫자를 실시간 그래프로 그립니다. Arduino·ESP32 같은 보드, 센서 모듈, 값을 보내는 장비·PLC 의 출력을 눈으로 확인하고 기록할 때 씁니다.

  • 받는 곳: 시리얼(포트·속도·8N1), TCP 클라이언트(장비 포트에 접속), UDP 받기(멀티캐스트 포함).
  • 해석: 글자 줄(쉼표·빈칸·탭·세미콜론 자동), «이름:값»(Arduino 시리얼 플로터 식), 머리글 줄을 채널 이름으로, 바이너리 프레임(시작 바이트·u8~f64·엔디언·체크섬).
  • 그래프: 채널 32개까지(색·켜고 끄기·이름·왼쪽/오른쪽 축), 최근 N점/N초, Y 자동·고정, 멈춤(받기는 계속), 커서 값, 두 점의 Δt·Δ값, 확대·옮기기.
  • 표(최근·최소·최대·평균), 원시 수신(실패 줄 빨강·이유), 받는 동안 CSV 기록, 보이는 범위 CSV·PNG 저장.
  • 무료(GPL-3.0)이고 화면은 한국어·영어입니다.

처음 쓰는 순서

  • 1. 장비가 한 줄에 숫자를 보내게 합니다. Arduino 예: Serial.print(t); Serial.print(','); Serial.println(h); → «23.1,40». 이름을 붙이려면 Serial.print("temp:"); … → «temp:23.1,hum:40».
  • 2. 왼쪽 «받는 곳» 시리얼 → 포트와 속도(스케치의 Serial.begin 값). TCP 면 장비 주소·포트, UDP 면 이 PC 의 받을 포트.
  • 3. «해석» 은 «글자 줄»·구분자 «자동» 그대로 두면 대부분 됩니다.
  • 4. «받기 시작»(F4). 값이 오면 그래프와 아래 «채널» 표가 생깁니다. 숫자가 안 보이면 «원시 수신» 탭에서 실제로 무엇이 오는지 봅니다.
  • 5. 기록하려면 «● CSV 기록», 지금 화면만 남기려면 «화면 CSV»·«PNG».

화면 구성

  • 왼쪽: 받는 곳(시리얼·TCP·UDP)과 설정, «해석»(데이터 모양·구분자·머리글 또는 바이너리 프레임), 받기 시작·멈추기와 상태, 받은 양(값 줄·실패·줄/초·바이트).
  • 가운데 위 도구 막대: ⏸ 멈춤·▶ 실시간, 보기(최근 점·최근 초와 폭), Y 자동·고정(오른쪽 축을 쓰는 채널이 있으면 «Y 오른쪽» 도), ● CSV 기록, 화면 CSV, PNG, 지우기.
  • 가운데: 그래프(위에 범례), 그 아래 측정 줄(A·B·Δt·Δ값).
  • 아래: 탭 «채널»(보기·색·이름·축·최근·최소·최대·평균) / «원시 수신». 위아래 사이 막대를 끌어 높이를 바꿉니다(두 번 누르면 처음 높이).
  • 머리줄 📌: 항상 위 — 이 창을 다른 창 위에 늘 보이게 합니다(설정의 «항상 위» 와 같음).
  • 창 제목에 지금 상태가 나옵니다(예: «COM3 115200 8N1 · 연결됨 ● REC — PortDock Serial»). 작업 표시줄에서 어느 창이 어느 포트인지 알 수 있습니다.
  • 창 너비가 900px 이하(화면 반쪽 맞춤 등)면 왼쪽 연결 설정 칸이 접히고, 위에 요약 줄과 «⚙ 연결 설정»·연결 버튼이 나옵니다. «⚙ 연결 설정» 으로 펼치고 ✕ 나 바깥을 눌러 닫습니다.

받는 곳

  • 시리얼: 포트·속도·데이터 비트·패리티·정지 비트(보통 8N1). «고급 연결» 의 «DTR 켜기»(기본 켬)는 네이티브 USB 보드(Leonardo·ESP32-S2/S3·RP2040 등)가 보내기 시작하게 합니다 — Uno 같은 보드는 열 때 한 번 리셋됩니다. «뽑혔다 꽂히면 다시 연결»(기본 켬).
  • TCP 클라이언트: 이 PC 가 장비의 주소·포트에 접속해 받습니다. 끊기면 2초마다 다시 접속합니다. (장비가 PC 에 접속해 오는 서버 방식은 PortDock TCP 로 받아 보세요.)
  • UDP 받기: 이 PC 의 «받을 주소»(0.0.0.0 = 모든 랜카드)·포트로 오는 데이터그램. 데이터그램 하나가 줄 끝 없이 와도 한 줄로 봅니다. 장비가 멀티캐스트로 보내면 «멀티캐스트 그룹» 에 그 주소.
  • 받는 중에는 받는 곳 설정이 잠기고, «해석» 은 바꿀 수 있습니다(바꾸면 줄 조각·채널 이름을 새로 시작).

글자 줄 해석

  • 줄 끝은 LF·CR LF·CR 어느 것이든 됩니다. 빈 줄은 건너뜁니다. 줄 끝 없이 4096바이트가 쌓이면 잘라서 실패 줄로 남깁니다.
  • 구분자 «자동»: 줄에 탭이 있으면 탭, 없으면 세미콜론, 쉼표, 빈칸 순. 세미콜론·탭·빈칸으로 나눌 때는 «1,5» 를 1.5 로 읽습니다(유럽식 소수점). 끝에 붙은 구분자(«1,2,»)는 빈 칸으로 치지 않습니다.
  • 숫자: 23 · -1.5 · +1.0E+00 · 0x1F(16진). «1,,3» 의 가운데처럼 빈 칸은 빈 값(선이 끊김). 숫자가 아닌 칸은 빈 값이 되고 그 줄은 «원시 수신» 에 빨강·이유(«숫자가 아닌 칸 2: «abc»»)로 남습니다.
  • «이름:값»: temp:23.1,hum:40 · temp:23.1 hum:40 · a=1 b=2 · «temp: 23.1»(빈칸) 모두 됩니다. 이름마다 채널이 정해지고(처음 나온 순서) 순서가 바뀌어 와도 같은 채널에 들어갑니다. 한 줄에 이름 없는 숫자가 섞이면 자리 번호(«2»)가 이름이 됩니다.
  • 머리글: 숫자가 하나도 없고 칸이 둘 이상인 줄(time,volt,amp)은 채널 이름이 됩니다. 장비가 다시 보내면 이름도 바뀝니다. «쓰지 않음» 이면 그런 줄은 실패 줄입니다. «Ready» 처럼 한 낱말 줄은 이름이 아니라 실패 줄입니다.
  • 채널은 32개까지 — 넘는 칸은 버리고 이유를 남깁니다.

바이너리 프레임

  • 프레임 = [시작 바이트…][값 × 채널 수][체크섬]. 길이는 정해져 있고 왼쪽에 «프레임 n 바이트 = 시작 + 값 + 체크섬» 으로 보입니다.
  • 시작 바이트(HEX, 예 «AA 55», 8개까지): 이것을 찾아 프레임을 맞춥니다. 찾느라 버린 바이트는 «원시 수신» 에 «시작 바이트를 찾느라 n바이트 버림». 비우면 받은 순서대로 길이마다 자릅니다 — 한 바이트라도 어긋나면 체크섬이 있어야 다시 맞춥니다.
  • 값 형식: u8·i8·u16·i16·u32·i32·f32·f64. 바이트 순서: 리틀 엔디언(Arduino·ESP32·PC 의 기본) 또는 빅 엔디언.
  • 체크섬: SUM8·XOR(BCC)·CRC8·CRC16 Modbus·CCITT·XMODEM·LRC·SUM16·CRC32. 기본은 시작 바이트 뒤부터 체크섬 앞까지 계산(«체크섬에 시작 바이트 포함» 으로 바꿈). 틀린 프레임은 버리고 한 바이트 밀어 다시 찾습니다.
  • Arduino 예: byte f[7] = {0xAA, 0x55}; int16_t a = analogRead(A0), b = analogRead(A1); memcpy(f+2,&a,2); memcpy(f+4,&b,2); f[6] = f[2]+f[3]+f[4]+f[5]; Serial.write(f,7); → 시작 «AA 55», 채널 2, i16, 리틀 엔디언, 체크섬 SUM8.
  • 길이 칸이 있는 가변 길이 프레임은 아직 하지 않습니다.

그래프 보기

  • 보기 «최근 점»: 받은 순서 번호를 가로축으로 최근 N점(기본 1000). «최근 초»: PC 가 받은 시각으로 최근 N초 — 장비 시각이 아니라 USB·네트워크가 묶어 넘기는 시각이라 점 간격이 고르지 않을 수 있습니다(정확한 간격이 필요하면 장비가 시각·카운터를 한 채널로 보내세요).
  • 버퍼는 최근 10만 줄입니다(1 kHz 면 약 100초). 그보다 긴 기록은 «● CSV 기록» 으로.
  • Y «자동» 은 보이는 값에 맞추고, «고정» 은 최소·최대. 채널 «축» 을 오른쪽으로 두면 오른쪽 축이 생기고 «Y 오른쪽» 을 따로 정합니다.
  • ⏸ 멈춤(Space): 그래프만 멈추고 받기·기록은 계속합니다. ▶ 실시간(End, 또는 그래프 두 번 누르기)으로 돌아갑니다. 멈춘 사이 오래 받으면 보던 범위가 버퍼에서 밀려날 수 있습니다.
  • 휠: 마우스 자리를 기준으로 가로 확대·축소. Shift+휠: 세로. 끌기: 옮기기(Shift+끌기는 세로도). 확대·옮기기를 하면 저절로 멈춥니다.
  • 커서: 그래프 위에 마우스를 올리면 가장 가까운 점의 번호·시각과 채널 값이 나옵니다.
  • 측정: 그래프를 누르면 측정점 A, 한 번 더 누르면 B. 아래 줄에 Δt(시각 차)·Δn(점 수)·1/Δt(Hz)와 채널마다 Δ값. 세 번째 누르기는 새 A. 오른쪽 버튼·Esc·«측정점 지우기» 로 지웁니다.
  • 선이 점보다 픽셀이 적으면 픽셀마다 처음·최소·최대·마지막 값으로 그려 뾰족한 값도 사라지지 않습니다. 점이 적으면 점도 찍습니다.

채널 표·원시 수신

  • «채널» 탭: 채널마다 보기(켜고 끄기), 색(기본 8색은 색약에도 구별되게 고른 색, 9번째부터는 같은 색 점선), 이름(비우면 장비가 보낸 이름 또는 CH1…), 축(왼쪽·오른쪽), 최근 값과 지금 보이는 범위의 최소·최대·평균.
  • «원시 수신» 탭: 최근 300줄. 해석 실패 줄은 빨강과 이유, 연결·끊김 같은 사건은 회색. 바이너리면 프레임 HEX.
  • 왼쪽 받은 양: 값 줄·실패 수·초당 줄·바이트. 화면이 따라오지 못해 버린 줄이 있으면 따로 알립니다(CSV 기록에는 모두 남음).

기록과 저장

  • «● CSV 기록»(Ctrl+Shift+L): 받는 동안 모든 값을 파일에 바로 씁니다 — 시각(로컬, ms), elapsed_s(기록 시작부터 초), 채널. 첫 줄은 채널 이름(그때의 이름). 엑셀에서 한글이 깨지지 않게 BOM 을 붙입니다. 그래프를 멈추거나 버퍼에서 밀려나도 파일에는 남고, 1초마다 디스크에 씁니다.
  • «화면 CSV»(Ctrl+S): 지금 보이는 범위만 — time·elapsed_s·index(받은 순서)·채널.
  • «PNG»: 그래프 그림(범례·눈금·측정점 포함). «지우기»(Ctrl+L): 버퍼·그래프·원시 줄·측정점을 비웁니다.

Simulator 로 따라하기 (장비 없이)

장비가 없으면 PortDock Simulator 의 «장비가 먼저 보내기» 로 같은 PC 에서 값을 흘려 봅니다.

  • 1. PortDock Simulator 를 열고 방식 «UDP» — «받을 포트» 5006, «보낼 곳» 127.0.0.1 : 5005 로 두고 «시작».
  • 2. «장비가 먼저 보내기» 를 펼쳐 ASCII, 내용 «temp:2{rand 0..4 dec}.{rand 0..9 dec},hum:{rand 40..45 dec},n:{counter dec}», «줄 끝 붙이기» CR LF.
  • 3. «반복(ms)» 100 을 켭니다 — 0.1초마다 «temp:23.4,hum:41,n:0» 처럼 값이 바뀌어 나갑니다({rand}·{counter} 는 보낼 때마다 새로 채움).
  • 4. PortDock Plot: 받는 곳 «UDP 받기», 받을 주소 0.0.0.0, 포트 5005 → «받기 시작». temp·hum·n 세 채널이 생깁니다. n 은 크기가 달라 «축» 을 오른쪽으로 두면 보기 좋습니다.
  • 5. 그래프를 두 번 눌러 측정점 A·B 사이 Δn 과 n 의 Δ값이 같은지 보고, «● CSV 기록» 을 켰다 끈 뒤 엑셀로 열어 봅니다.
  • 시리얼로 하려면 가상 COM 쌍(com0com 등)의 한쪽을 Simulator, 다른 쪽을 Plot 에 엽니다. TCP 면 Simulator «TCP 서버» 포트 5000, Plot «TCP 클라이언트» 127.0.0.1:5000.
  • 실패 줄 보기: 내용을 «temp:{rand 0..9 dec}x» 처럼 바꾸면 «원시 수신» 에 빨간 줄과 이유가 나옵니다.

범위 밖 (아직 하지 않음)

  • TCP 서버(장비가 접속해 오는 방식), MQTT·BLE·Modbus 폴링 — Modbus 값의 추세는 PortDock Modbus Master 의 «추세» 를 쓰세요.
  • 길이 칸이 있는 가변 길이 바이너리 프레임, 채널마다 배율·오프셋, XY(리사주) 그래프, FFT, 저장한 CSV 다시 열기.
  • 장비로 보내기(명령) — PortDock Serial·TCP·UDP 를 함께 쓰세요(같은 포트를 두 프로그램이 동시에 열 수는 없습니다).

설정 (⚙)

  • 언어, 테마, 글자 크기. 설정 내보내기·가져오기는 받는 곳·해석·보기·채널 이름과 색을 JSON 파일로 옮깁니다.
  • «항상 위»: 이 창을 다른 창 위에 늘 보이게 합니다(머리줄 📌 과 같은 값).
  • «모두 펼치기(전문가 화면)»: 평소 접어 두는 칸(고급 연결·받기 설정·장애 주입·통계·찾는 방법·트리거·자동응답 등)을 펼친 채 보입니다. 켜 둔 채 하나를 접으면 이번 실행 동안만 접힙니다. 끄면 칸마다 기억해 둔 열림 상태로 돌아갑니다.

단축키

  • F4: 받기 시작·멈추기(왼쪽 버튼과 같음).
  • Space: 그래프 멈춤·이어 보기(입력칸·버튼 밖에서 — 받기와 CSV 기록은 계속).
  • End: 실시간 보기로(확대·옮기기를 버림). 그래프를 두 번 눌러도 같습니다.
  • Esc: 측정점 A·B 지우기(입력칸 밖에서).
  • Ctrl+S: 화면 CSV 저장(보이는 범위만). Ctrl+Shift+L: CSV 기록 켜기·끄기. Ctrl+L: 지우기(버퍼·그래프·원시 줄·측정점, 기록 파일은 그대로).
  • F1 또는 화면의 ? 버튼: 이 도움말. Esc 로 닫습니다.
  • 숫자 칸: ↑/↓ 1씩, Shift+↑/↓ 10씩, PageUp/PageDown 100씩, 칸을 누른 뒤 마우스 휠. 속도 칸은 ↑/↓ 로 목록의 다음·앞 속도.
  • 대화상자가 열려 있거나 한글을 조합하는 중에는 단축키가 동작하지 않습니다.

문제 해결

  • 그래프가 비어 있음: «원시 수신» 을 봅니다. 아무것도 없으면 속도·포트·DTR(네이티브 USB 보드), TCP·UDP 면 주소·포트·방화벽. 글자가 깨져 보이면 속도가 틀렸습니다.
  • 빨간 줄 «숫자가 없습니다»: 장비가 설명 글(«Ready» 등)을 보냅니다 — 무시해도 됩니다. 값 줄이 빨가면 구분자나 형식이 다릅니다(구분자를 직접 골라 보세요).
  • 값이 엉뚱한 채널로 감: 줄마다 칸 수·순서가 바뀌면 자리로 나뉩니다 — 장비에서 «이름:값» 으로 보내면 순서가 바뀌어도 같은 채널.
  • 바이너리 값이 엉뚱함: 엔디언·형식·채널 수를 확인하고, «원시 수신» 의 HEX 로 프레임 경계를 봅니다.
  • «포트가 사용 중»: Arduino IDE 의 시리얼 모니터·플로터나 다른 터미널을 닫으세요.
  • 프로그램이 열리지 않음: Microsoft Edge WebView2 가 필요합니다(Windows 11 에는 들어 있음).