# PROJECT_KNOWLEDGE.md — Весовой контроллер ESP32 > Последнее обновление: 2026-05-03 > Автор: Алексей (admin@zeroday.su) ## Назначение проекта ESP32-based весовой контроллер для автомобильной грузовой платформенной весовой системы. Индикатор: **Zemic TITAN 9** (основан на Zemic A12E). Грузоподъёмность платформы — до 50 тонн. **Задачи контроллера:** - Приём данных весов по RS232 (через MAX3232 → Serial2) - Передача данных на сервер по MQTT over Ethernet (W5500) - Управление светофором (2-канальное реле: красный / зелёный сигнал) - Локальный веб-интерфейс на ESP32 (статус + IP) --- ## Стек технологий ### Железо (Hardware) | Компонент | Модель | Примечание | |---|---|---| | МК | ESP32 Dev Module | Arduino IDE, ESP32 core 3.x (Espressif) | | Ethernet | W5500 зелёный, компактный 3.3V | Первый синий модуль был дефектный (RJ45 трансформатор не работал) | | RS232 → TTL | MAX3232 | Для согласования уровней 12V RS232 и 3.3V ESP32 | | RTC | DS3231 | Обнаружение нестабильное — требует инициализации **до** ETH.begin() | | Реле | 2-канальный оптоизолированный модуль | Управление через BC547 транзисторы | | Питание | 5V 2A PSU | | ### Подключение W5500 → ESP32 | W5500 | ESP32 GPIO | Примечание | |---|---|---| | MOSI | GPIO 23 | На модуле MOSI/MISO физически перепутаны — компенсировано в прошивке | | MISO | GPIO 19 | (MISO/MOSI swapped на плате) | | SCK | GPIO 18 | | | CS | GPIO 4 | GPIO5 — strapping pin, вызывал конфликты SPI при инициализации | | RST | GPIO 26 | | | INT | GPIO 27 | Не используется | ### Подключение MAX3232 → ESP32 | MAX3232 (TTL сторона) | ESP32 GPIO | |---|---| | TX (TTL out) | GPIO 16 (RX2) | | RX (TTL in) | GPIO 17 (TX2) — не используется | | VCC | 3V3 | | GND | GND | ### Подключение весов Zemic TITAN 9 | DB25 пин весов | Куда | |---|---| | Пин 2 (TXD) | MAX3232 RX (RS232 сторона) | | Пин 7 (GND) | Общий GND | ### Реле (управление светофором) | GPIO ESP32 | Реле | Сигнал | |---|---|---| | GPIO 32 | Канал 1 | Красный | | GPIO 33 | Канал 2 | Зелёный | --- ## Прошивка (Firmware) **Файл:** `firmware/scales_controller.ino` **Библиотеки:** - `ETH.h` — нативная библиотека ESP32 core 3.x (Espressif) для W5500 - `NetworkClient`, `NetworkUDP` — из ESP32 core 3.x - `PubSubClient` (Nick O'Leary) — MQTT клиент - `ArduinoJson` (Benoit Blanchon) — сериализация JSON - `RTClib` — DS3231 RTC **Ключевые параметры прошивки:** ```cpp // Ethernet SPI #define ETH_SPI_SCK 18 #define ETH_SPI_MISO 19 // Физически MOSI на плате (swapped!) #define ETH_SPI_MOSI 23 // Физически MISO на плате (swapped!) #define ETH_PHY_CS 4 // Не GPIO5! (strapping pin) #define ETH_PHY_RST 26 #define ETH_PHY_IRQ 27 // UART (весы) #define SCALES_BAUD 9600 // P3 в меню весов // Реле #define RELAY_RED_PIN 32 #define RELAY_GREEN_PIN 33 // MQTT (тестовая фаза) const char* MQTT_HOST = "77.222.43.248"; // или scales.zeroday.su const int MQTT_PORT = 1884; // plain MQTT const char* MQTT_USER = "esp32"; const char* MQTT_TOPIC = "scales/weighing/event"; ``` **Порядок инициализации в setup() (критично!):** 1. `Wire.begin(21, 22)` → DS3231 RTC 2. `SPI.begin(SCK, MISO, MOSI)` → W5500 3. `ETH.begin(...)` → Ethernet 4. `mqttClient.setServer(...)` → MQTT 5. `Serial2.begin(9600, ...)` → RS232 от весов --- ## Сервер (Backend) **Сервер:** `scales.zeroday.su` **IP:** `77.222.43.248` **ОС:** Ubuntu 24 **Директория проекта:** `/var/www/scales/` ### Структура директории ``` /var/www/scales/ ├── server.js # Node.js Express + WebSocket + MQTT subscriber ├── public/ │ └── index.html # Дашборд (реальное время, история, светофор, график) ├── node_modules/ └── package.json ``` ### Стек сервера | Компонент | Версия / Конфиг | |---|---| | Node.js | LTS | | Express | HTTP + WebSocket (ws) | | MQTT клиент | mqtt (npm) | | PM2 | Процесс: `scales` (id=13), порт 3016 | | Mosquitto | MQTT broker, конфиг: `/etc/mosquitto/conf.d/acs.conf` | | nginx | Reverse proxy + SSL termination | | SSL | Let's Encrypt (certbot), домен `scales.zeroday.su` | | PostgreSQL | Установлен, для будущей персистентности (пока in-memory) | ### Переменные окружения (server.js) ```js const PORT = 3016; const MQTT_BROKER = 'mqtt://localhost:1883'; const MQTT_USER = 'scales-server'; // MQTT_PASS — хранится в server.js, не публикуется const MQTT_TOPIC = 'scales/weighing/event'; const MAX_HISTORY = 100; // событий в памяти ``` ### MQTT Конфигурация **Файл:** `/etc/mosquitto/conf.d/acs.conf` ``` listener 1883 127.0.0.1 # для Node.js бэкенда listener 1884 0.0.0.0 # для ESP32 (plain, тестовый) allow_anonymous false password_file /etc/mosquitto/passwd ``` **Пользователи MQTT:** | Пользователь | Роль | |---|---| | `esp32` | ESP32 контроллер (publisher) | | `scales-server` | Node.js backend (subscriber) | *Пароли хранятся в `/etc/mosquitto/passwd`, в документацию не включаются.* ### nginx - HTTPS → порт 3016 (proxy_pass) - WebSocket upgrade: `Upgrade $http_upgrade; Connection "upgrade"` - MQTTS stream proxy: порт 8883 → localhost:1883 (запланировано, настроено в nginx stream) **Конфиг:** `/etc/nginx/sites-available/scales.zeroday.su` **Stream:** nginx.conf (stream блок в конце) ### REST API (server.js) | Endpoint | Метод | Описание | |---|---|---| | `/api/status` | GET | Статус MQTT, uptime, последнее событие | | `/api/history` | GET | Последние 100 событий взвешивания | | WebSocket `/` | WS | Реалтайм события + инит состояния | --- ## Формат данных весов ### RS232 строка от TITAN 9 / A12E ``` ww000.000kg — брутто wn000.000kg — нетто wt000.000kg — тара ``` ASCII, 9600 бод, 8N1. ### MQTT JSON payload ```json { "device_id": "scales_01", "timestamp": "2026-03-27T16:35:25Z", "weight_kg": 15420.5, "weight_raw": "ww015420.500kg", "stable": true, "plate": null } ``` Топик: `scales/weighing/event`, QoS: 1, Retain: false. --- ## Параметры весов Zemic TITAN 9 | Параметр | Назначение | Нужное значение | |---|---|---| | P3 | Скорость RS232 | 9600 (по умолчанию) | | P4 | Формат вывода | Стандартный `ww000.000kg` | | P5 | Режим передачи | **3** (передача при стабильном весе) — **НЕ НАСТРОЕН** | **Пароль сервисного меню:** `1` --- ## Текущий статус проекта (на 2026-05-03) ✅ ESP32 инициализирует W5500 и подключается к MQTT ✅ Backend задеплоен, дашборд работает на https://scales.zeroday.su ✅ MQTT авторизация настроена ✅ Relay логика реализована в прошивке ❌ Весы не передают RS232 — параметр P5 = "нет передачи" (не изменён) ❌ DS3231 обнаруживается нестабильно ⏳ MQTTS (порт 8883) настроен в nginx, но не активирован в прошивке --- ## Контакты и ресурсы - Zemic support (настройка P5): +7 (472) 277-71-19 - Репозиторий: https://git.zeroday.su/admin/weighing-controller - Дашборд: https://scales.zeroday.su