Files
smart-trainer/docs/wiring.html
sm c76ca89cc9 Initial commit: project docs and wiring diagram
Smart bench press trainer with electric motor (M365 Pro).
CAN Bus architecture: ESP32-S3 (master) + Flipsky 75100 (VESC) + STM32 Blue Pill (carriage).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 19:03:55 +03:00

509 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="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Схема подключения v4 — CAN Bus</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600;700&family=Outfit:wght@300;400;600;700&display=swap');
:root {
--bg: #08090e; --card-bg: #111620; --border: #1a2030;
--text: #c8d6e5; --dim: #4e5e74; --label: #e2e8f0;
--red: #ef4444; --green: #22c55e; --cyan: #22d3ee;
--amber: #f59e0b; --purple: #8b5cf6; --pink: #f43f5e;
--teal: #2dd4bf; --orange: #fb923c; --blue: #3b82f6;
--indigo: #818cf8;
}
* { margin:0; padding:0; box-sizing:border-box; }
body { background:var(--bg); color:var(--text); font-family:'Outfit',sans-serif; }
code, .mono { font-family:'JetBrains Mono',monospace; }
/* ── Header ── */
.header { text-align:center; padding:20px 16px 12px; border-bottom:1px solid var(--border); }
.header h1 { font-size:18px; font-weight:700; color:var(--label); }
.header p { font-size:11px; color:var(--dim); margin-top:3px; font-family:'JetBrains Mono',monospace; }
/* ── Section ── */
.section { max-width:1100px; margin:0 auto; padding:14px 12px 4px; }
.section-title {
font-size:10px; font-weight:600; color:var(--dim);
text-transform:uppercase; letter-spacing:1.5px; margin-bottom:8px;
padding-left:4px; border-left:3px solid var(--border);
}
/* ── Grid layouts ── */
.grid-2 { display:grid; grid-template-columns:1fr 1fr; gap:8px; }
.grid-3 { display:grid; grid-template-columns:1fr 1fr 1fr; gap:8px; }
.grid-4 { display:grid; grid-template-columns:repeat(auto-fit, minmax(200px, 1fr)); gap:8px; }
/* ── Module card ── */
.mod {
background:var(--card-bg); border:1px solid var(--border);
border-radius:8px; padding:12px 14px; position:relative;
}
.mod:hover { border-color:#2a3a50; }
.mod-head { display:flex; align-items:center; gap:6px; margin-bottom:6px; }
.mod-dot { width:8px; height:8px; border-radius:50%; flex-shrink:0; }
.mod-name { font-size:12px; font-weight:700; color:var(--label); }
.mod-tag {
font-size:8px; font-family:'JetBrains Mono',monospace;
padding:1px 5px; border-radius:3px; margin-left:auto;
}
.mod-desc { font-size:10px; color:#5a6a80; line-height:1.6; font-family:'JetBrains Mono',monospace; }
.mod-pins { margin-top:6px; font-size:9px; color:#7a8a9e; font-family:'JetBrains Mono',monospace; line-height:1.7; }
.mod-pins .pin { display:flex; gap:6px; }
.mod-pins .pin-dir { color:var(--dim); width:16px; text-align:center; }
.mod-pins .pin-name { color:#9aa8ba; }
.mod-pins .pin-dest { color:var(--dim); margin-left:auto; }
/* ── CAN bus bar ── */
.can-bus {
max-width:1100px; margin:0 auto; padding:0 12px;
}
.can-bar {
background:linear-gradient(90deg, #082828, #0a3535, #082828);
border:1.5px solid var(--cyan); border-radius:8px;
padding:12px 20px; display:flex; align-items:center;
justify-content:space-between; position:relative;
}
.can-bar::before {
content:''; position:absolute; top:50%; left:20px; right:20px;
height:3px; background:var(--cyan); opacity:.2; border-radius:2px;
}
.can-node {
position:relative; z-index:1; text-align:center;
background:#0b1520; border:1px solid var(--cyan);
border-radius:6px; padding:6px 14px;
}
.can-node-id { font-size:10px; font-weight:700; color:var(--cyan); font-family:'JetBrains Mono',monospace; }
.can-node-name { font-size:8px; color:#5a8a8a; font-family:'JetBrains Mono',monospace; }
.can-term {
font-size:8px; color:var(--cyan); font-family:'JetBrains Mono',monospace;
background:#061518; border:1px solid #1a4a4a; border-radius:4px;
padding:2px 8px; position:relative; z-index:1;
}
.can-info {
text-align:center; margin-top:6px; font-size:9px;
color:#155e75; font-family:'JetBrains Mono',monospace;
}
/* ── Wire description ── */
.wire {
font-size:9px; font-family:'JetBrains Mono',monospace;
padding:3px 8px; border-radius:4px; display:inline-flex;
align-items:center; gap:5px; margin:2px 0;
}
.wire::before { content:''; width:14px; height:2px; border-radius:1px; }
.wire-red::before { background:var(--red); } .wire-red { color:#fca5a5; }
.wire-cyan::before { background:var(--cyan); } .wire-cyan { color:#67e8f9; }
.wire-amber::before { background:var(--amber); } .wire-amber { color:#fcd34d; }
.wire-green::before { background:var(--green); } .wire-green { color:#86efac; }
.wire-pink::before { background:var(--pink); } .wire-pink { color:#fda4af; }
.wire-purple::before { background:var(--indigo); } .wire-purple { color:#c4b5fd; }
.wire-orange::before { background:var(--orange); } .wire-orange { color:#fdba74; }
.wire-teal::before { background:var(--teal); } .wire-teal { color:#99f6e4; }
/* ── Data flow table ── */
.flow-table { width:100%; font-size:10px; font-family:'JetBrains Mono',monospace; border-collapse:collapse; }
.flow-table th { color:var(--dim); text-align:left; padding:4px 8px; border-bottom:1px solid #1a2a3a; font-weight:400; }
.flow-table td { padding:4px 8px; color:#7a9aba; }
.flow-table tr:hover td { color:var(--label); }
/* ── BOM table ── */
.bom-table { width:100%; font-size:10px; font-family:'JetBrains Mono',monospace; border-collapse:collapse; }
.bom-table td { padding:3px 8px; color:#64748b; }
.bom-table td:last-child { text-align:right; }
.bom-table tr.total td { color:var(--label); font-weight:700; border-top:1px solid var(--border); padding-top:6px; }
/* ── Legend ── */
.legend { max-width:1100px; margin:8px auto; padding:0 12px; display:flex; flex-wrap:wrap; gap:10px; justify-content:center; }
.legend-i { display:flex; align-items:center; gap:4px; font-size:9px; font-family:'JetBrains Mono',monospace; color:#5a6a80; }
.legend-l { width:18px; height:3px; border-radius:2px; }
</style>
</head>
<body>
<!-- ════════════════════════════════════════════════════════════════ -->
<!-- HEADER -->
<!-- ════════════════════════════════════════════════════════════════ -->
<div class="header">
<h1>Схема подключения v4 — CAN Bus архитектура</h1>
<p>3 узла CAN · Waveshare ESP32-S3 · STM32F103 Blue Pill · Flipsky 75100 Pro V2 · 250 Кбит/с</p>
</div>
<!-- ════════════════════════════════════════════════════════════════ -->
<!-- SECTION: СИЛОВАЯ ЧАСТЬ -->
<!-- ════════════════════════════════════════════════════════════════ -->
<div class="section">
<div class="section-title">Силовая часть</div>
<div class="grid-4">
<!-- MODULE: Питание 220В + Батарея -->
<div class="mod" id="mod-power">
<div class="mod-head">
<div class="mod-dot" style="background:var(--blue)"></div>
<span class="mod-name">Питание</span>
</div>
<div class="mod-desc">
Сеть 220В → щит (автомат + УЗО)<br>
→ БП 48В → батарея 48В 100-250Вт·ч<br>
Батарея = буфер рекуперации + UPS<br>
Заряд до 90% (буфер для рекуп.)<br>
DC-DC 48→5V · LDO 3.3V на узлах
</div>
<div class="mod-pins">
<div class="pin"><span class="pin-dir"></span><span class="pin-name">+48V</span><span class="pin-dest">→ VESC BAT+</span></div>
<div class="pin"><span class="pin-dir"></span><span class="pin-name">GND</span><span class="pin-dest">→ общая шина</span></div>
<div class="pin"><span class="pin-dir"></span><span class="pin-name">5V</span><span class="pin-dest">→ ESP32, STM32</span></div>
</div>
</div>
<!-- MODULE: Flipsky VESC -->
<div class="mod" id="mod-vesc">
<div class="mod-head">
<div class="mod-dot" style="background:var(--green)"></div>
<span class="mod-name">Flipsky 75100 Pro V2</span>
<span class="mod-tag" style="background:#0f2518;color:#86efac;">CAN ID:10</span>
</div>
<div class="mod-desc">
VESC 6.0 · 100А · 84В макс · ~$90<br>
FOC current control · BT встроен<br>
Фазный EMI фильтр на плате
</div>
<div class="mod-pins">
<div class="pin"><span class="pin-dir"></span><span class="pin-name">BAT+/GND</span><span class="pin-dest">← батарея 48В</span></div>
<div class="pin"><span class="pin-dir"></span><span class="pin-name">CAN_H/L</span><span class="pin-dest">↔ CAN шина</span></div>
<div class="pin"><span class="pin-dir"></span><span class="pin-name">Ph A/B/C</span><span class="pin-dest">→ реле НЗ → мотор</span></div>
<div class="pin"><span class="pin-dir"></span><span class="pin-name">HALL 5p</span><span class="pin-dest">← мотор Hall U/V/W</span></div>
<div class="pin"><span class="pin-dir"></span><span class="pin-name">MOT TEMP</span><span class="pin-dest">← мотор NTC 10K</span></div>
<div class="pin"><span class="pin-dir"></span><span class="pin-name">BRAKE RES</span><span class="pin-dest">→ тормозной резистор</span></div>
</div>
</div>
<!-- MODULE: Реле НЗ -->
<div class="mod" id="mod-relay">
<div class="mod-head">
<div class="mod-dot" style="background:var(--pink)"></div>
<span class="mod-name">Реле НЗ ×3 (40А)</span>
</div>
<div class="mod-desc">
3× авто-реле НЗ, катушки параллельно<br>
или 3-фазный контактор НЗ на DIN-рейку<br>
Опц. резистор 0.1-0.3Ω в цепи КЗ
</div>
<div class="mod-pins">
<div class="pin"><span class="pin-dir"></span><span class="pin-name">Ph A/B/C вход</span><span class="pin-dest">← VESC фазы</span></div>
<div class="pin"><span class="pin-dir"></span><span class="pin-name">Ph A/B/C выход</span><span class="pin-dest">→ мотор</span></div>
<div class="pin"><span class="pin-dir"></span><span class="pin-name">Катушка</span><span class="pin-dest">← Watchdog OUT</span></div>
</div>
</div>
<!-- MODULE: Мотор -->
<div class="mod" id="mod-motor">
<div class="mod-head">
<div class="mod-dot" style="background:var(--amber)"></div>
<span class="mod-name">Мотор M365 Pro</span>
</div>
<div class="mod-desc">
BLDC 350W · 15pp · Outrunner<br>
Барабан D30мм · Кабестан 3 витка<br>
90 имп/об → ~1мм разрешение хода
</div>
<div class="mod-pins">
<div class="pin"><span class="pin-dir"></span><span class="pin-name">Ph A/B/C</span><span class="pin-dest">← реле НЗ</span></div>
<div class="pin"><span class="pin-dir"></span><span class="pin-name">Hall U/V/W</span><span class="pin-dest">→ VESC HALL</span></div>
<div class="pin"><span class="pin-dir"></span><span class="pin-name">NTC 10K</span><span class="pin-dest">→ VESC MOT TEMP</span></div>
</div>
</div>
<!-- MODULE: Тормозной резистор -->
<div class="mod" id="mod-brake-resistor">
<div class="mod-head">
<div class="mod-dot" style="background:var(--orange)"></div>
<span class="mod-name">Тормозной резистор</span>
</div>
<div class="mod-desc">
100-200Вт · 1-5Ом · через MOSFET<br>
Сброс рекуперации при полной батарее<br>
Flipsky поддерживает нативно<br>
Расположение: щит (вентиляция!)
</div>
<div class="mod-pins">
<div class="pin"><span class="pin-dir"></span><span class="pin-name">BRAKE RES</span><span class="pin-dest">← VESC разъём</span></div>
</div>
</div>
<!-- MODULE: Watchdog -->
<div class="mod" id="mod-watchdog">
<div class="mod-head">
<div class="mod-dot" style="background:var(--pink)"></div>
<span class="mod-name">Watchdog 50мс</span>
</div>
<div class="mod-desc">
555 / TPL5010 · таймаут 50мс<br>
ESP32 шлёт импульсы ~100Гц<br>
Сбой → реле отпускает → КЗ фаз<br>
Торможение ~150кг при 0.5 м/с
</div>
<div class="mod-pins">
<div class="pin"><span class="pin-dir"></span><span class="pin-name">WDI</span><span class="pin-dest">← ESP32 GPIO</span></div>
<div class="pin"><span class="pin-dir"></span><span class="pin-name">OUT</span><span class="pin-dest">→ катушка реле НЗ</span></div>
</div>
</div>
</div>
</div>
<!-- ════════════════════════════════════════════════════════════════ -->
<!-- CAN BUS BAR -->
<!-- ════════════════════════════════════════════════════════════════ -->
<div class="can-bus" style="padding-top:12px;">
<div class="section-title" style="max-width:1100px;margin:0 auto 8px;padding-left:16px;">CAN Bus · 250 Кбит/с · витая пара</div>
<div class="can-bar">
<div class="can-term">120Ω</div>
<div class="can-node">
<div class="can-node-id">ID:20 МАСТЕР</div>
<div class="can-node-name">ESP32 Waveshare</div>
</div>
<div class="can-node">
<div class="can-node-id">ID:10</div>
<div class="can-node-name">VESC Flipsky</div>
</div>
<div class="can-node">
<div class="can-node-id">ID:30 КАРЕТКА</div>
<div class="can-node-name">STM32 Blue Pill</div>
</div>
<div class="can-term">120Ω</div>
</div>
<div class="can-info">4 провода к каретке: CAN_H · CAN_L · 5V · GND (гибкий шлейф вдоль направляющей)</div>
</div>
<!-- ════════════════════════════════════════════════════════════════ -->
<!-- SECTION: УПРАВЛЕНИЕ -->
<!-- ════════════════════════════════════════════════════════════════ -->
<div class="section">
<div class="section-title">Управление (CAN узлы #2 и #3)</div>
<div class="grid-2">
<!-- MODULE: Waveshare ESP32-S3 -->
<div class="mod" id="mod-esp32">
<div class="mod-head">
<div class="mod-dot" style="background:var(--purple)"></div>
<span class="mod-name">Waveshare ESP32-S3 LCD 3.5"</span>
<span class="mod-tag" style="background:#1a1040;color:#c4b5fd;">CAN ID:20 · МАСТЕР</span>
</div>
<div class="mod-desc">
ESP32-S3R8 · 240МГц · WiFi/BLE5 · ~$20<br>
3.5" IPS тачскрин 320×480 (ST7796 + FT6336)<br>
QMI8658 IMU (борт) · PCF85063 RTC · AXP2101 PMU<br>
TF-карта (лог тренировок) · TWAI (CAN) встроен<br>
Расположение: верхняя перекладина, тачскрин к спортсмену
</div>
<div class="mod-pins">
<div class="pin"><span class="pin-dir"></span><span class="pin-name">TWAI TX/RX</span><span class="pin-dest">→ SN65HVD230 ($1) → CAN шина</span></div>
<div class="pin"><span class="pin-dir"></span><span class="pin-name">GPIO WDG_OUT</span><span class="pin-dest">→ Watchdog WDI (~100Гц)</span></div>
<div class="pin"><span class="pin-dir"></span><span class="pin-name">GPIO END_LO</span><span class="pin-dest">← концевик НИЗ (НЗ, RC 1К+100нФ)</span></div>
<div class="pin"><span class="pin-dir"></span><span class="pin-name">GPIO END_HI</span><span class="pin-dest">← концевик ВЕРХ (НЗ, RC 1К+100нФ)</span></div>
<div class="pin"><span class="pin-dir"></span><span class="pin-name">SPI</span><span class="pin-dest">↔ RC522 NFC (идентификация)</span></div>
<div class="pin"><span class="pin-dir"></span><span class="pin-name">BLE 5</span><span class="pin-dest">↔ смартфон (беспроводное)</span></div>
</div>
</div>
<!-- MODULE: Blue Pill STM32 — Carriage -->
<div class="mod" id="mod-stm32">
<div class="mod-head">
<div class="mod-dot" style="background:var(--teal)"></div>
<span class="mod-name">STM32F103C8T6 Blue Pill</span>
<span class="mod-tag" style="background:#0a2020;color:#5eead4;">CAN ID:30 · КАРЕТКА</span>
</div>
<div class="mod-desc">
Cortex-M3 72МГц · CAN 2.0B встроен · ~$2<br>
Расположение: на каретке штанги (движется)<br>
Кабель: 4 пров. гибкий шлейф к CAN шине
</div>
<div class="mod-pins">
<div class="pin"><span class="pin-dir"></span><span class="pin-name">CAN TX/RX</span><span class="pin-dest">→ SN65HVD230 ($1) → CAN шина</span></div>
<div class="pin"><span class="pin-dir"></span><span class="pin-name">I2C SDA/SCL</span><span class="pin-dest">← MPU6050 (провод 3 см)</span></div>
<div class="pin"><span class="pin-dir"></span><span class="pin-name">GPIO SCK/DT</span><span class="pin-dest">← HX711 (провод 3 см)</span></div>
</div>
<div style="margin-top:8px;padding:6px 8px;background:#0d2828;border-radius:5px;">
<div class="mod-desc" style="color:#2dd4bf;">
<strong>Локальные датчики (на каретке):</strong><br>
• MPU6050 — 6-осевой IMU · I2C · 200 Гц · ~$2<br>
• HX711 + тензодатчик S-тип 200кг · GPIO · 80 Гц · ~$8<br>
• Тензодатчик inline: каретка ↔ трос<br>
→ CAN фрейм: accel[3] + gyro[3] + force(Н)
</div>
</div>
</div>
</div>
</div>
<!-- ════════════════════════════════════════════════════════════════ -->
<!-- SECTION: ПЕРИФЕРИЯ -->
<!-- ════════════════════════════════════════════════════════════════ -->
<div class="section">
<div class="section-title">Периферия (локально на ESP32)</div>
<div class="grid-4">
<div class="mod" id="mod-endstops">
<div class="mod-head">
<div class="mod-dot" style="background:var(--orange)"></div>
<span class="mod-name">Концевики ×2</span>
</div>
<div class="mod-desc">
Нижний (homing) + Верхний (аварийный)<br>
НЗ · pull-up 10K · RC-фильтр 1К+100нФ<br>
Debounce 10-20мс программный<br>
GPIO ESP32 напрямую · ~$2
</div>
</div>
<div class="mod" id="mod-nfc">
<div class="mod-head">
<div class="mod-dot" style="background:var(--indigo)"></div>
<span class="mod-name">RC522 NFC</span>
</div>
<div class="mod-desc">
SPI · идентификация пользователей<br>
Профили нагрузок по карте<br>
~$3
</div>
</div>
<div class="mod" id="mod-phone">
<div class="mod-head">
<div class="mod-dot" style="background:var(--indigo)"></div>
<span class="mod-name">Смартфон</span>
</div>
<div class="mod-desc">
BLE 5 (встроен ESP32-S3)<br>
Настройки · статистика · профили<br>
Беспроводное подключение
</div>
</div>
<div class="mod" id="mod-tf">
<div class="mod-head">
<div class="mod-dot" style="background:#64748b"></div>
<span class="mod-name">TF карта</span>
</div>
<div class="mod-desc">
Встроена в Waveshare<br>
Логирование тренировок<br>
SDIO интерфейс
</div>
</div>
<div class="mod" id="mod-flipsky-bt">
<div class="mod-head">
<div class="mod-dot" style="background:var(--green)"></div>
<span class="mod-name">Flipsky BT</span>
</div>
<div class="mod-desc">
Встроен в 75100 Pro V2<br>
VESC Tool · калибровка FOC<br>
Настройка лимитов тока/температуры
</div>
</div>
</div>
</div>
<!-- ════════════════════════════════════════════════════════════════ -->
<!-- SECTION: DATA FLOW -->
<!-- ════════════════════════════════════════════════════════════════ -->
<div class="section">
<div class="section-title">CAN Data Flow</div>
<div class="grid-2">
<div class="mod" id="mod-dataflow">
<table class="flow-table">
<tr><th>ID</th><th>Узел</th><th></th><th>Данные</th><th>Частота</th></tr>
<tr style="color:#86efac"><td>10</td><td>Flipsky 75100</td><td>→ шина</td><td>ERPM, I_mot, T_mot, V_bat</td><td>100 Гц</td></tr>
<tr style="color:#c4b5fd"><td>20</td><td>ESP32 Waveshare</td><td>→ VESC</td><td>set_current(I_ref)</td><td>100 Гц</td></tr>
<tr style="color:#5eead4"><td>30</td><td>STM32 Blue Pill</td><td>→ шина</td><td>accel[3], gyro[3], F(Н)</td><td>200 Гц</td></tr>
</table>
<div class="mod-desc" style="margin-top:8px;color:var(--dim);">
Загрузка шины: ~30% при 250 Кбит/с · запас для расширения
</div>
</div>
<div class="mod" id="mod-safety-summary">
<div class="mod-head">
<div class="mod-dot" style="background:var(--pink)"></div>
<span class="mod-name">Цепь безопасности (аппаратная)</span>
</div>
<div class="mod-desc" style="color:#fca5a5;">
ESP32 GPIO ~100Гц → Watchdog 555 (50мс)<br>
→ катушка 3× реле НЗ 40А<br>
→ при сбое: фазы КЗ → электромагнитное торможение<br>
→ F = Kt²·v / (R·r²) ≈ 150 кг при 0.5 м/с<br><br>
Дополнительно:<br>
• Тормозной резистор (overvoltage protection)<br>
• VESC max input voltage лимит<br>
• Софтовый лимит позиции по ERPM<br>
• Концевики (homing + аварийный стоп)
</div>
</div>
</div>
</div>
<!-- ════════════════════════════════════════════════════════════════ -->
<!-- SECTION: BOM -->
<!-- ════════════════════════════════════════════════════════════════ -->
<div class="section">
<div class="section-title">BOM — Оценка стоимости</div>
<div class="grid-2">
<div class="mod" id="mod-bom-electronics">
<div class="mod-head">
<span class="mod-name">Электроника</span>
</div>
<table class="bom-table">
<tr><td>Waveshare ESP32-S3 LCD 3.5"</td><td>~$20</td></tr>
<tr><td>Flipsky 75100 Pro V2</td><td>~$90</td></tr>
<tr><td>Blue Pill STM32F103</td><td>~$2</td></tr>
<tr><td>SN65HVD230 ×2</td><td>~$2</td></tr>
<tr><td>MPU6050 + HX711 + тензодат. S-тип</td><td>~$10</td></tr>
<tr><td>3× реле НЗ 40А / контактор</td><td>~$15</td></tr>
<tr><td>Watchdog 555 + обвязка</td><td>~$2</td></tr>
<tr><td>RC522 NFC + концевики ×2</td><td>~$5</td></tr>
<tr><td>DC-DC 48→5V</td><td>~$5</td></tr>
<tr><td>Тормозной резистор 100Вт</td><td>~$5</td></tr>
<tr class="total"><td>Итого электроника</td><td>~$156</td></tr>
</table>
</div>
<div class="mod" id="mod-bom-power-mech">
<div class="mod-head">
<span class="mod-name">Силовая + механика</span>
</div>
<table class="bom-table">
<tr><td>Батарея 48V 100-250Вт·ч (буфер)</td><td>~$100</td></tr>
<tr><td>БП 48В от сети 220В</td><td>~$25</td></tr>
<tr><td>Щит 220В (автомат + УЗО)</td><td>~$20</td></tr>
<tr><td>Мотор M365 Pro (б/у)</td><td>~$60</td></tr>
<tr><td>Рама + направляющие + механика</td><td>~$120</td></tr>
<tr class="total"><td>Итого сил. + мех.</td><td>~$325</td></tr>
<tr class="total" style="font-size:12px"><td>ОБЩИЙ ИТОГ</td><td>≈ $480</td></tr>
</table>
</div>
</div>
</div>
<!-- ════════════════════════════════════════════════════════════════ -->
<!-- LEGEND -->
<!-- ════════════════════════════════════════════════════════════════ -->
<div class="legend" style="padding-bottom:20px;">
<div class="legend-i"><div class="legend-l" style="background:var(--red)"></div>Питание</div>
<div class="legend-i"><div class="legend-l" style="background:var(--amber)"></div>Фазы A/B/C</div>
<div class="legend-i"><div class="legend-l" style="background:var(--cyan)"></div>CAN Bus</div>
<div class="legend-i"><div class="legend-l" style="background:var(--green)"></div>Hall</div>
<div class="legend-i"><div class="legend-l" style="background:var(--pink)"></div>Безопасность</div>
<div class="legend-i"><div class="legend-l" style="background:var(--indigo)"></div>SPI/данные</div>
<div class="legend-i"><div class="legend-l" style="background:var(--orange)"></div>GPIO</div>
<div class="legend-i"><div class="legend-l" style="background:var(--teal)"></div>Каретка</div>
</div>
</body>
</html>