POSA_LEAKSMS/raspberry_pi4_sht30/WIRING.html
cw2007 96c5205f61 feat(deploy): 센서별 배선도·핀맵 HTML + 번들 생성기 반영
- raspberry_pi4/WIRING.html, raspberry_pi4_sht30/WIRING.html 추가:
  자체 완결형(인라인 CSS/SVG, 외부참조 0 → 폐쇄망 오프라인 열람) 40핀 핀맵 도해
  + 핀맵 표 + 배선 스키매틱 + 전기설계 경고 + 설치 체크리스트. 인쇄 대응.
  누수 노드(Pi-A/Pi-C 공통, GPIO17)·SHT30 노드(I2C1, 0x44) 각 1장.
- make_deploy_bundles.py: TEXT_EXTS 에 .html 추가(번들 복사 시 CRLF→LF 정규화),
  Pi SETUP.md 에 WIRING.html 안내 줄 추가. copy_tree 가 각 Pi 번들에 자동 포함.
  (동반: 기존 dotfile .htaccess/.gitignore LF 정규화 반영.)
2026-07-03 09:28:16 +09:00

557 lines
28 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>온습도 노드 배선·핀맵 — Pi-B / SHT30 (sensor_id=2)</title>
<style>
:root{
--ink:#1a1d21; --muted:#5c6570; --line:#dfe3e8; --bg:#eef1f4; --card:#ffffff;
--accent:#1971c2; --accent-d:#155a9c; --warn:#e03131; --warnbg:#fff5f5;
--ok:#2f9e44; --gnd:#343a40; --chip:#eef2f6; --code:#0b3d2e;
--mono:"D2Coding","Consolas","Menlo","Courier New",ui-monospace,monospace;
--sans:"Malgun Gothic","Apple SD Gothic Neo","Noto Sans KR","Segoe UI",system-ui,-apple-system,sans-serif;
}
*{box-sizing:border-box;}
html,body{margin:0;padding:0;}
body{
font-family:var(--sans); color:var(--ink); background:var(--bg);
line-height:1.6; -webkit-font-smoothing:antialiased;
}
.wrap{max-width:1000px; margin:0 auto; padding:22px 18px 60px;}
/* ---------- Header ---------- */
.hero{
background:linear-gradient(135deg,#1f2933 0%,#283746 55%,#2f4a5a 100%);
color:#fff; border-radius:16px; padding:26px 28px;
box-shadow:0 8px 24px rgba(20,30,40,.18);
}
.hero .eyebrow{font-size:12.5px; letter-spacing:.14em; text-transform:uppercase;
color:#9fc3e0; font-weight:700; margin:0 0 6px;}
.hero h1{margin:0 0 8px; font-size:27px; line-height:1.25; font-weight:800;}
.hero p.sum{margin:0 0 16px; font-size:14.5px; color:#d7e2ec; max-width:72ch;}
.chips{display:flex; flex-wrap:wrap; gap:8px;}
.chip{
display:inline-flex; align-items:center; gap:6px;
background:rgba(255,255,255,.12); border:1px solid rgba(255,255,255,.22);
color:#eef5fb; font-size:12.5px; font-weight:600; padding:5px 11px; border-radius:999px;
}
.chip.mono{font-family:var(--mono); letter-spacing:.01em;}
.chip b{color:#fff;}
/* ---------- Sections ---------- */
section{
background:var(--card); border:1px solid var(--line); border-radius:14px;
padding:22px 24px; margin-top:20px; box-shadow:0 2px 10px rgba(20,30,40,.05);
}
h2{
display:flex; align-items:center; gap:11px; margin:0 0 16px;
font-size:19px; font-weight:800; color:var(--ink);
}
h2 .n{
flex:0 0 auto; width:30px; height:30px; border-radius:9px;
background:var(--accent); color:#fff; font-size:15px; font-weight:800;
display:flex; align-items:center; justify-content:center;
}
h2 small{font-weight:600; font-size:13px; color:var(--muted);}
/* ---------- Pinmap SVG ---------- */
.svg-pin{display:block; width:100%; max-width:460px; height:auto; margin:2px auto 0;}
.diagram-cap{text-align:center; color:var(--muted); font-size:12.5px; margin:12px 0 0;}
.legend{
display:flex; flex-wrap:wrap; justify-content:center; gap:12px 18px;
margin:16px auto 2px; max-width:640px;
}
.legend span{display:inline-flex; align-items:center; gap:7px; font-size:12.5px; color:var(--ink);}
.sw{width:15px; height:15px; border-radius:50%; flex:0 0 auto; border:1px solid rgba(0,0,0,.15);}
.sw.pwr{background:#2f9e44;} .sw.i2c{background:#1971c2;}
.sw.gnd{background:#343a40;}
.sw.altgnd{background:#ced4da; border:1.5px dashed #868e96;}
.sw.off{background:#dee2e6;}
/* SVG element classes */
.p-pwr{fill:#2f9e44; stroke:#248a3b; stroke-width:1.5;}
.p-i2c{fill:#1971c2; stroke:#155a9c; stroke-width:1.5;}
.p-gnd{fill:#343a40; stroke:#1f2429; stroke-width:1.5;}
.p-altgnd{fill:#ced4da; stroke:#868e96; stroke-width:1.5; stroke-dasharray:3 2;}
.p-off{fill:#dee2e6; stroke:#c3c9cf; stroke-width:1;}
.rail{fill:#f1f3f5; stroke:#ced4da; stroke-width:1.5;}
.pnum{font-family:var(--mono); font-size:12px; font-weight:700; text-anchor:middle; dominant-baseline:central;}
.pnum-l{fill:#ffffff;} .pnum-d{fill:#495057;}
.plbl{font-family:var(--mono); font-size:12px; dominant-baseline:central;}
.lbl-l{text-anchor:end;} .lbl-r{text-anchor:start;}
.lbl-used{fill:#1a1d21; font-weight:700;}
.lbl-alt{fill:#5c6570; font-weight:600;}
.lbl-off{fill:#adb5bd; font-weight:500;}
.cap-svg{font-family:var(--sans); font-size:12.5px; fill:#5c6570; font-weight:600; text-anchor:middle;}
/* ---------- Table ---------- */
table{width:100%; border-collapse:collapse; font-size:14px;}
thead th{
background:#f1f4f7; color:#2b3541; text-align:left; font-weight:700;
padding:10px 12px; border-bottom:2px solid #ccd4dc; font-size:13px;
}
tbody td{padding:11px 12px; border-bottom:1px solid var(--line); vertical-align:top;}
tbody tr:last-child td{border-bottom:none;}
.mono{font-family:var(--mono);}
.pinbadge{
display:inline-block; min-width:26px; text-align:center; font-family:var(--mono);
font-weight:700; font-size:13px; color:#fff; background:var(--accent);
border-radius:6px; padding:2px 7px;
}
.pinbadge.gnd{background:var(--gnd);} .pinbadge.pwr{background:var(--ok);}
.pinbadge.na{background:#adb5bd;}
td .warn-inline{color:var(--warn); font-weight:700;}
/* ---------- Schematic ---------- */
.svg-sch{display:block; width:100%; max-width:840px; height:auto; margin:0 auto;}
.box{fill:#f8f9fa; stroke:#495057; stroke-width:2; rx:8;}
.boxtitle{font-family:var(--sans); font-size:14px; font-weight:800; fill:#1a1d21; text-anchor:middle;}
.term{font-family:var(--mono); font-size:12.5px; font-weight:700; fill:#2b3541;}
.w-pwr{stroke:#e03131; stroke-width:3; fill:none; stroke-linecap:round; stroke-linejoin:round;}
.w-i2c{stroke:#1971c2; stroke-width:3; fill:none; stroke-linecap:round; stroke-linejoin:round;}
.w-gnd{stroke:#343a40; stroke-width:3; fill:none; stroke-linecap:round; stroke-linejoin:round;}
.w-addr{stroke:#495057; stroke-width:2.5; fill:none; stroke-dasharray:6 4; stroke-linecap:round;}
.res{fill:#ffffff; stroke:#212529; stroke-width:2;}
.wlbl{font-family:var(--sans); font-size:12px; font-weight:700; fill:#2b3541;}
.rlbl{font-family:var(--mono); font-size:12px; font-weight:700; fill:#b02a2a;}
.jn{fill:#212529;}
.sch-note{color:var(--muted); font-size:12.5px; text-align:center; margin:12px 0 0;}
/* ---------- Callouts ---------- */
.warn{
background:var(--warnbg); border:1.5px solid #ffc9c9; border-left:6px solid var(--warn);
border-radius:12px; padding:16px 18px; margin:0 0 16px; display:flex; gap:14px; align-items:flex-start;
}
.warn .ic{flex:0 0 auto; width:34px; height:34px;}
.warn h3{margin:0 0 4px; color:#c92a2a; font-size:16px; font-weight:800;}
.warn p{margin:0; font-size:14px; color:#5a2020;}
.warn b{color:#c92a2a;}
ul.notes{margin:6px 0 0; padding:0; list-style:none;}
ul.notes li{position:relative; padding:7px 0 7px 24px; border-bottom:1px dashed var(--line); font-size:14px;}
ul.notes li:last-child{border-bottom:none;}
ul.notes li::before{content:""; position:absolute; left:4px; top:14px; width:8px; height:8px;
background:var(--accent); border-radius:2px; transform:rotate(45deg);}
code, .kbd{font-family:var(--mono); background:#eef2f6; color:#0b3d2e; padding:1px 6px; border-radius:5px; font-size:13px;}
.cmd{
font-family:var(--mono); background:#12211b; color:#c8f7d8; border-radius:10px;
padding:12px 14px; font-size:13.5px; margin:12px 0 0; overflow-x:auto;
}
.cmd .cm{color:#7fd6a3;} .cmd .ok{color:#ffd43b;}
/* ---------- Checklist ---------- */
ol.check{margin:0; padding:0; list-style:none; counter-reset:ck;}
ol.check li{
counter-increment:ck; position:relative; display:flex; align-items:flex-start; gap:12px;
padding:11px 4px 11px 0; border-bottom:1px solid var(--line); font-size:14px;
}
ol.check li:last-child{border-bottom:none;}
ol.check li .num{
flex:0 0 auto; width:24px; height:24px; border-radius:50%; background:#e7eef5; color:#1f5f97;
font-weight:800; font-size:12.5px; display:flex; align-items:center; justify-content:center;
}
ol.check li .num::before{content:counter(ck);}
ol.check li .cbox{flex:0 0 auto; width:18px; height:18px; border:2px solid #9aa6b1; border-radius:4px; margin-top:1px;}
ol.check li .txt{flex:1;}
ol.check li .txt b{color:var(--warn);}
footer{margin-top:26px; text-align:center; color:var(--muted); font-size:12px;}
/* ---------- Print ---------- */
@media print{
body{background:#fff;}
.wrap{max-width:none; padding:0;}
.hero{background:#fff !important; color:#111; border:2px solid #111; box-shadow:none;}
.hero .eyebrow{color:#444;} .hero p.sum{color:#222;}
.chip{background:#f2f2f2; color:#111; border:1px solid #999;}
.chip b{color:#000;}
h2 .n{background:#111;}
section{box-shadow:none; border:1px solid #999; break-inside:avoid; page-break-inside:avoid;}
table, tr, td, th, .warn, .card{break-inside:avoid; page-break-inside:avoid;}
.svg-pin, .svg-sch{max-width:100%;}
.cmd{background:#f2f2f2; color:#111; border:1px solid #999;}
a{color:#000;}
}
@media (max-width:560px){
.hero h1{font-size:22px;} h2{font-size:17px;}
}
</style>
</head>
<body>
<div class="wrap">
<!-- ============ 1. HEADER ============ -->
<header class="hero">
<p class="eyebrow">현장 설치 문서 · 배선 &amp; 핀맵</p>
<h1>온습도 노드 — 1번 지점 / 서버실</h1>
<p class="sum">
SHT30 온습도 센서를 라즈베리파이(Pi-B)의 I2C(버스 1, 주소 0x44)에 연결하는 측정 노드입니다.
이 노드는 측정값만 <b>5분 주기</b>로 서버에 보고하며, 고온·저온·고습·저습 임계 판정과 SMS 발송은 서버가 담당합니다.
</p>
<div class="chips">
<span class="chip">Raspberry Pi 4 Model B</span>
<span class="chip mono">BCM2711</span>
<span class="chip">Raspberry Pi OS Bookworm 64-bit</span>
<span class="chip">Sensirion SHT30 (한진데이터 P4422-3)</span>
<span class="chip mono">I2C bus <b>1</b></span>
<span class="chip mono">addr <b>0x44</b></span>
<span class="chip mono">sensor_id=<b>2</b></span>
<span class="chip">보고 주기 5분</span>
</div>
</header>
<!-- ============ 2. PINMAP SVG ============ -->
<section>
<h2><span class="n">2</span>40핀 헤더 핀맵 도해 <small>사용 핀만 강조 · 나머지는 회색</small></h2>
<svg class="svg-pin" viewBox="0 0 520 672" role="img" aria-label="라즈베리파이 40핀 GPIO 헤더 핀맵">
<!-- caption -->
<text class="cap-svg" x="260" y="20">40핀 GPIO 헤더 (J8) · 물리 핀 번호</text>
<!-- rails -->
<rect class="rail" x="186" y="46" width="28" height="600" rx="14"/>
<rect class="rail" x="306" y="46" width="28" height="600" rx="14"/>
<!-- Row 1 : pin1 (square = pin1 marker) / pin2 -->
<rect class="p-pwr" x="188" y="48" width="24" height="24" rx="5"/>
<text class="pnum pnum-l" x="200" y="60">1</text>
<text class="plbl lbl-l lbl-used" x="176" y="60">3V3</text>
<circle class="p-off" cx="320" cy="60" r="12"/>
<text class="pnum pnum-d" x="320" y="60">2</text>
<text class="plbl lbl-r lbl-off" x="344" y="60">5V</text>
<!-- Row 2 : pin3 / pin4 -->
<circle class="p-i2c" cx="200" cy="90" r="12"/>
<text class="pnum pnum-l" x="200" y="90">3</text>
<text class="plbl lbl-l lbl-used" x="176" y="90">GPIO2 (SDA1)</text>
<circle class="p-off" cx="320" cy="90" r="12"/>
<text class="pnum pnum-d" x="320" y="90">4</text>
<text class="plbl lbl-r lbl-off" x="344" y="90">5V</text>
<!-- Row 3 : pin5 / pin6 -->
<circle class="p-i2c" cx="200" cy="120" r="12"/>
<text class="pnum pnum-l" x="200" y="120">5</text>
<text class="plbl lbl-l lbl-used" x="176" y="120">GPIO3 (SCL1)</text>
<circle class="p-gnd" cx="320" cy="120" r="12"/>
<text class="pnum pnum-l" x="320" y="120">6</text>
<text class="plbl lbl-r lbl-used" x="344" y="120">GND</text>
<!-- Row 4 : pin7 / pin8 -->
<circle class="p-off" cx="200" cy="150" r="12"/>
<text class="pnum pnum-d" x="200" y="150">7</text>
<text class="plbl lbl-l lbl-off" x="176" y="150">GPIO4</text>
<circle class="p-off" cx="320" cy="150" r="12"/>
<text class="pnum pnum-d" x="320" y="150">8</text>
<text class="plbl lbl-r lbl-off" x="344" y="150">GPIO14 (TXD)</text>
<!-- Row 5 : pin9 / pin10 -->
<circle class="p-altgnd" cx="200" cy="180" r="12"/>
<text class="pnum pnum-d" x="200" y="180">9</text>
<text class="plbl lbl-l lbl-alt" x="176" y="180">GND</text>
<circle class="p-off" cx="320" cy="180" r="12"/>
<text class="pnum pnum-d" x="320" y="180">10</text>
<text class="plbl lbl-r lbl-off" x="344" y="180">GPIO15 (RXD)</text>
<!-- Row 6 : pin11 / pin12 -->
<circle class="p-off" cx="200" cy="210" r="12"/>
<text class="pnum pnum-d" x="200" y="210">11</text>
<text class="plbl lbl-l lbl-off" x="176" y="210">GPIO17</text>
<circle class="p-off" cx="320" cy="210" r="12"/>
<text class="pnum pnum-d" x="320" y="210">12</text>
<text class="plbl lbl-r lbl-off" x="344" y="210">GPIO18</text>
<!-- Row 7 : pin13 / pin14 -->
<circle class="p-off" cx="200" cy="240" r="12"/>
<text class="pnum pnum-d" x="200" y="240">13</text>
<text class="plbl lbl-l lbl-off" x="176" y="240">GPIO27</text>
<circle class="p-altgnd" cx="320" cy="240" r="12"/>
<text class="pnum pnum-d" x="320" y="240">14</text>
<text class="plbl lbl-r lbl-alt" x="344" y="240">GND</text>
<!-- Row 8 : pin15 / pin16 -->
<circle class="p-off" cx="200" cy="270" r="12"/>
<text class="pnum pnum-d" x="200" y="270">15</text>
<text class="plbl lbl-l lbl-off" x="176" y="270">GPIO22</text>
<circle class="p-off" cx="320" cy="270" r="12"/>
<text class="pnum pnum-d" x="320" y="270">16</text>
<text class="plbl lbl-r lbl-off" x="344" y="270">GPIO23</text>
<!-- Row 9 : pin17 / pin18 -->
<circle class="p-off" cx="200" cy="300" r="12"/>
<text class="pnum pnum-d" x="200" y="300">17</text>
<text class="plbl lbl-l lbl-off" x="176" y="300">3V3</text>
<circle class="p-off" cx="320" cy="300" r="12"/>
<text class="pnum pnum-d" x="320" y="300">18</text>
<text class="plbl lbl-r lbl-off" x="344" y="300">GPIO24</text>
<!-- Row 10 : pin19 / pin20 -->
<circle class="p-off" cx="200" cy="330" r="12"/>
<text class="pnum pnum-d" x="200" y="330">19</text>
<text class="plbl lbl-l lbl-off" x="176" y="330">GPIO10 (MOSI)</text>
<circle class="p-altgnd" cx="320" cy="330" r="12"/>
<text class="pnum pnum-d" x="320" y="330">20</text>
<text class="plbl lbl-r lbl-alt" x="344" y="330">GND</text>
<!-- Row 11 : pin21 / pin22 -->
<circle class="p-off" cx="200" cy="360" r="12"/>
<text class="pnum pnum-d" x="200" y="360">21</text>
<text class="plbl lbl-l lbl-off" x="176" y="360">GPIO9 (MISO)</text>
<circle class="p-off" cx="320" cy="360" r="12"/>
<text class="pnum pnum-d" x="320" y="360">22</text>
<text class="plbl lbl-r lbl-off" x="344" y="360">GPIO25</text>
<!-- Row 12 : pin23 / pin24 -->
<circle class="p-off" cx="200" cy="390" r="12"/>
<text class="pnum pnum-d" x="200" y="390">23</text>
<text class="plbl lbl-l lbl-off" x="176" y="390">GPIO11 (SCLK)</text>
<circle class="p-off" cx="320" cy="390" r="12"/>
<text class="pnum pnum-d" x="320" y="390">24</text>
<text class="plbl lbl-r lbl-off" x="344" y="390">GPIO8 (CE0)</text>
<!-- Row 13 : pin25 / pin26 -->
<circle class="p-altgnd" cx="200" cy="420" r="12"/>
<text class="pnum pnum-d" x="200" y="420">25</text>
<text class="plbl lbl-l lbl-alt" x="176" y="420">GND</text>
<circle class="p-off" cx="320" cy="420" r="12"/>
<text class="pnum pnum-d" x="320" y="420">26</text>
<text class="plbl lbl-r lbl-off" x="344" y="420">GPIO7 (CE1)</text>
<!-- Row 14 : pin27 / pin28 -->
<circle class="p-off" cx="200" cy="450" r="12"/>
<text class="pnum pnum-d" x="200" y="450">27</text>
<text class="plbl lbl-l lbl-off" x="176" y="450">GPIO0 (ID_SD)</text>
<circle class="p-off" cx="320" cy="450" r="12"/>
<text class="pnum pnum-d" x="320" y="450">28</text>
<text class="plbl lbl-r lbl-off" x="344" y="450">GPIO1 (ID_SC)</text>
<!-- Row 15 : pin29 / pin30 -->
<circle class="p-off" cx="200" cy="480" r="12"/>
<text class="pnum pnum-d" x="200" y="480">29</text>
<text class="plbl lbl-l lbl-off" x="176" y="480">GPIO5</text>
<circle class="p-altgnd" cx="320" cy="480" r="12"/>
<text class="pnum pnum-d" x="320" y="480">30</text>
<text class="plbl lbl-r lbl-alt" x="344" y="480">GND</text>
<!-- Row 16 : pin31 / pin32 -->
<circle class="p-off" cx="200" cy="510" r="12"/>
<text class="pnum pnum-d" x="200" y="510">31</text>
<text class="plbl lbl-l lbl-off" x="176" y="510">GPIO6</text>
<circle class="p-off" cx="320" cy="510" r="12"/>
<text class="pnum pnum-d" x="320" y="510">32</text>
<text class="plbl lbl-r lbl-off" x="344" y="510">GPIO12</text>
<!-- Row 17 : pin33 / pin34 -->
<circle class="p-off" cx="200" cy="540" r="12"/>
<text class="pnum pnum-d" x="200" y="540">33</text>
<text class="plbl lbl-l lbl-off" x="176" y="540">GPIO13</text>
<circle class="p-altgnd" cx="320" cy="540" r="12"/>
<text class="pnum pnum-d" x="320" y="540">34</text>
<text class="plbl lbl-r lbl-alt" x="344" y="540">GND</text>
<!-- Row 18 : pin35 / pin36 -->
<circle class="p-off" cx="200" cy="570" r="12"/>
<text class="pnum pnum-d" x="200" y="570">35</text>
<text class="plbl lbl-l lbl-off" x="176" y="570">GPIO19</text>
<circle class="p-off" cx="320" cy="570" r="12"/>
<text class="pnum pnum-d" x="320" y="570">36</text>
<text class="plbl lbl-r lbl-off" x="344" y="570">GPIO16</text>
<!-- Row 19 : pin37 / pin38 -->
<circle class="p-off" cx="200" cy="600" r="12"/>
<text class="pnum pnum-d" x="200" y="600">37</text>
<text class="plbl lbl-l lbl-off" x="176" y="600">GPIO26</text>
<circle class="p-off" cx="320" cy="600" r="12"/>
<text class="pnum pnum-d" x="320" y="600">38</text>
<text class="plbl lbl-r lbl-off" x="344" y="600">GPIO20</text>
<!-- Row 20 : pin39 / pin40 -->
<circle class="p-altgnd" cx="200" cy="630" r="12"/>
<text class="pnum pnum-d" x="200" y="630">39</text>
<text class="plbl lbl-l lbl-alt" x="176" y="630">GND</text>
<circle class="p-off" cx="320" cy="630" r="12"/>
<text class="pnum pnum-d" x="320" y="630">40</text>
<text class="plbl lbl-r lbl-off" x="344" y="630">GPIO21</text>
<!-- pin1 hint -->
<text class="cap-svg" x="260" y="662" style="font-size:11px;">■ 사각 표시 = 1번 핀 (기판 방향 기준)</text>
</svg>
<div class="legend">
<span><i class="sw pwr"></i>3.3V 전원 — 핀 1</span>
<span><i class="sw i2c"></i>I2C SDA/SCL — 핀 3·5</span>
<span><i class="sw gnd"></i>GND (사용) — 핀 6</span>
<span><i class="sw altgnd"></i>대체 GND (선택) — 9·14·20·25·30·34·39</span>
<span><i class="sw off"></i>미사용 핀</span>
</div>
<p class="diagram-cap">본 도해의 핀 번호·신호는 Raspberry Pi 4 Model B (BCM2711) 40핀 헤더 표준 배열과 일치합니다.</p>
</section>
<!-- ============ 3. PINMAP TABLE ============ -->
<section>
<h2><span class="n">3</span>핀맵 표 <small>SHT30 → 40핀 헤더</small></h2>
<table>
<thead>
<tr><th style="width:30%">신호</th><th style="width:24%">BCM</th><th style="width:14%">물리핀</th><th>비고</th></tr>
</thead>
<tbody>
<tr>
<td><b>3.3V 전원</b> (VCC)</td>
<td class="mono">—</td>
<td><span class="pinbadge pwr">1</span></td>
<td><span class="warn-inline">★ 반드시 3.3V — 5V(핀 2·4) 연결 금지</span></td>
</tr>
<tr>
<td><b>I2C 데이터</b> (SDA)</td>
<td class="mono">GPIO2 / SDA1</td>
<td><span class="pinbadge">3</span></td>
<td>4.7kΩ 풀업 → 3.3V <span style="color:var(--muted)">(모듈 내장 시 생략)</span></td>
</tr>
<tr>
<td><b>I2C 클럭</b> (SCL)</td>
<td class="mono">GPIO3 / SCL1</td>
<td><span class="pinbadge">5</span></td>
<td>4.7kΩ 풀업 → 3.3V <span style="color:var(--muted)">(모듈 내장 시 생략)</span></td>
</tr>
<tr>
<td><b>접지</b> (GND)</td>
<td class="mono">—</td>
<td><span class="pinbadge gnd">6</span></td>
<td>대체 GND 사용 가능: <span class="mono">9 · 14 · 20 · 25 · 30 · 34 · 39</span></td>
</tr>
<tr>
<td><b>주소 선택</b> (ADDR)</td>
<td class="mono">—</td>
<td><span class="pinbadge na">GND</span></td>
<td>ADDR → GND ⇒ <span class="mono">0x44</span> (선택) · ADDR → VDD ⇒ <span class="mono">0x45</span></td>
</tr>
</tbody>
</table>
</section>
<!-- ============ 4. SCHEMATIC SVG ============ -->
<section>
<h2><span class="n">4</span>배선 스키매틱 <small>센서 ↔ 헤더 ↔ 풀업 저항</small></h2>
<svg class="svg-sch" viewBox="0 0 840 400" role="img" aria-label="SHT30 배선 스키매틱">
<!-- component boxes -->
<rect class="box" x="70" y="90" width="150" height="290" rx="8"/>
<rect class="box" x="640" y="90" width="150" height="290" rx="8"/>
<text class="boxtitle" x="145" y="116">SHT30 센서 모듈</text>
<text class="boxtitle" x="715" y="116">Pi 40핀 헤더</text>
<!-- SHT30 terminal labels (right side) -->
<text class="term" x="210" y="150" text-anchor="end">VCC</text>
<text class="term" x="210" y="200" text-anchor="end">SDA</text>
<text class="term" x="210" y="250" text-anchor="end">SCL</text>
<text class="term" x="210" y="305" text-anchor="end">GND</text>
<text class="term" x="210" y="350" text-anchor="end">ADDR</text>
<!-- Pi terminal labels (left side) -->
<text class="term" x="650" y="150">3V3 (핀 1)</text>
<text class="term" x="650" y="200">SDA1 (핀 3)</text>
<text class="term" x="650" y="250">SCL1 (핀 5)</text>
<text class="term" x="650" y="305">GND (핀 6)</text>
<!-- POWER wire (also 3V3 rail for pull-ups) -->
<path class="w-pwr" d="M220 150 H640"/>
<text class="wlbl" x="300" y="140" fill="#b02a2a">전원 3.3V</text>
<!-- GND wire -->
<path class="w-gnd" d="M220 305 H640"/>
<text class="wlbl" x="300" y="322" fill="#2b3541">접지 GND</text>
<!-- SDA wire (with hop over SCL pull-up branch at x=480) -->
<path class="w-i2c" d="M220 200 H470 A10 9 0 0 1 490 200 H640"/>
<text class="wlbl" x="300" y="216" fill="#155a9c">SDA → GPIO2</text>
<!-- SCL wire -->
<path class="w-i2c" d="M220 250 H640"/>
<text class="wlbl" x="300" y="266" fill="#155a9c">SCL → GPIO3</text>
<!-- ADDR -> GND -->
<path class="w-addr" d="M220 350 H300 V305"/>
<text class="wlbl" x="228" y="368" fill="#3b444d">ADDR → GND = 0x44</text>
<circle class="jn" cx="300" cy="305" r="4"/>
<!-- Pull-up R1 on SDA (x=400) -->
<path class="w-i2c" d="M400 200 V190"/>
<rect class="res" x="390" y="165" width="20" height="25" rx="3"/>
<path class="w-i2c" d="M400 165 V150"/>
<circle class="jn" cx="400" cy="200" r="4"/>
<circle class="jn" cx="400" cy="150" r="4"/>
<text class="rlbl" x="416" y="180">R1 4.7kΩ</text>
<!-- Pull-up R2 on SCL (x=480), branch rises past SDA (hop) up to rail -->
<path class="w-i2c" d="M480 250 V188"/>
<rect class="res" x="470" y="163" width="20" height="25" rx="3"/>
<path class="w-i2c" d="M480 163 V150"/>
<circle class="jn" cx="480" cy="250" r="4"/>
<circle class="jn" cx="480" cy="150" r="4"/>
<text class="rlbl" x="496" y="178">R2 4.7kΩ</text>
</svg>
<p class="sch-note">
풀업 저항 R1·R2 (4.7kΩ ×2) 는 3.3V 레일로 연결됩니다. <b>SHT30 모듈에 내장되어 있으면 생략</b>하십시오.
SDA 선의 반원(hop)은 배선 교차 표시일 뿐 전기적 연결이 아닙니다.
</p>
</section>
<!-- ============ 5. ELECTRICAL NOTES ============ -->
<section>
<h2><span class="n">5</span>전기 설계 · 주의</h2>
<div class="warn">
<svg class="ic" viewBox="0 0 24 24" aria-hidden="true">
<path d="M12 2 L23 21 H1 Z" fill="#ffe3e3" stroke="#e03131" stroke-width="1.6" stroke-linejoin="round"/>
<line x1="12" y1="9" x2="12" y2="15" stroke="#e03131" stroke-width="2.2" stroke-linecap="round"/>
<circle cx="12" cy="18" r="1.4" fill="#e03131"/>
</svg>
<div>
<h3>치명적 경고 — 전원은 반드시 3.3V</h3>
<p>SHT30 의 <b>VCC 는 물리 핀 1 (3.3V)</b> 에만 연결하십시오.
<b>5V (핀 2·4) 연결 절대 금지</b> — 소자가 즉시 손상될 수 있습니다.
결선 전 핀 번호를 다시 확인하십시오.</p>
</div>
</div>
<ul class="notes">
<li><b>I2C 풀업:</b> SDA·SCL 각각 4.7kΩ 풀업 저항을 3.3V 로 연결. 센서 모듈에 내장된 경우 생략 가능.</li>
<li><b>주소 설정:</b> ADDR → GND 이면 <code>0x44</code>(기본), ADDR → VDD 이면 <code>0x45</code>. <code>config.py</code> 의 <code>I2C_ADDR</code> 값과 반드시 일치해야 합니다.</li>
<li><b>I2C 버스:</b> 버스 1 사용. 부팅 후 I2C 가 활성화되어 있어야 함(<code>raspi-config</code> 또는 <code>dtparam=i2c_arm=on</code>).</li>
<li><b>배선 길이:</b> I2C 는 짧은 케이블을 권장. 케이블이 길면 통신 오류·풀업 값 조정이 필요할 수 있습니다.</li>
<li><b>역할 분담:</b> 이 노드는 측정값만 5분 주기로 서버에 보고합니다. 고온·저온·고습·저습 <b>임계 판정과 SMS 발송은 서버</b>가 수행합니다.</li>
<li><b>설정 파일:</b> <code>raspberry_pi4_sht30/config.py</code> (<code>I2C_BUS=1</code>, <code>I2C_ADDR=0x44</code>). 기기별 값은 <code>config_local.py</code> 로 오버라이드.</li>
</ul>
<div class="cmd">
<span class="cm"># I2C 연결 확인 (0x44 가 표에 보이면 정상)</span>
$ i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
40: -- -- -- -- <span class="ok">44</span> -- -- -- -- -- -- -- -- -- -- --
</div>
</section>
<!-- ============ 6. INSTALL CHECKLIST ============ -->
<section>
<h2><span class="n">6</span>설치 체크리스트</h2>
<ol class="check">
<li><span class="num"></span><span class="cbox"></span><span class="txt"><b>전원 차단 상태</b>에서 배선 작업 (핫플러그 금지)</span></li>
<li><span class="num"></span><span class="cbox"></span><span class="txt">VCC → 물리 핀 1 (3.3V) 연결 — <b>5V 핀(2·4) 아님</b>을 재확인</span></li>
<li><span class="num"></span><span class="cbox"></span><span class="txt">GND → 물리 핀 6 연결 (대체 GND 사용 시 9·14·20·25·30·34·39)</span></li>
<li><span class="num"></span><span class="cbox"></span><span class="txt">SDA → 핀 3 (GPIO2), SCL → 핀 5 (GPIO3) 연결</span></li>
<li><span class="num"></span><span class="cbox"></span><span class="txt">풀업 저항 4.7kΩ ×2 를 SDA·SCL → 3.3V 로 연결 (모듈 내장 시 생략)</span></li>
<li><span class="num"></span><span class="cbox"></span><span class="txt">ADDR → GND 확인 (주소 0x44 선택)</span></li>
<li><span class="num"></span><span class="cbox"></span><span class="txt">결선 전체 재확인 후 Pi 전원 인가</span></li>
<li><span class="num"></span><span class="cbox"></span><span class="txt">I2C 활성화 확인 (raspi-config / dtparam=i2c_arm=on)</span></li>
<li><span class="num"></span><span class="cbox"></span><span class="txt"><code>i2cdetect -y 1</code> 실행 → <code>0x44</code> 표시 확인</span></li>
<li><span class="num"></span><span class="cbox"></span><span class="txt">config.py / config_local.py 의 I2C_BUS=1, I2C_ADDR=0x44 확인</span></li>
<li><span class="num"></span><span class="cbox"></span><span class="txt">측정 로그 및 서버 수신 확인 (5분 주기 보고 정상)</span></li>
</ol>
</section>
<footer>
온습도 노드 · Pi-B (sensor_id=2, 1번 지점/서버실) · SHT30 I2C 배선 문서 — 현장 인쇄용
</footer>
</div>
</body>
</html>