commit 35e5ffea1e5537559d2069d1f96bf802b7ad202c Author: admin Date: Thu Apr 30 12:26:31 2026 +0300 Initial: backup from Claude Project 'Весовое оборудование' - PROTOCOL.md: topology, JSON schema, MQTT topic, auth, retry logic - HARDWARE.md: components, GPIO map, ASCII wiring, power, calibration - FIRMWARE_NOTES.md: stack (ESP32 core 3.x), libraries, main loop, known issues, TODO - INDEX.md: manifest + current status + blockers Current blocker: TITAN 9 P5 default = no RS232 output. Fix: call Zemic +7(472)277-71-19, set P5=3, then test on-site. Related server repo: admin/scales diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0a5ece6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.DS_Store +*.swp +*.tmp +Thumbs.db +node_modules/ +build/ diff --git a/FIRMWARE_NOTES.md b/FIRMWARE_NOTES.md new file mode 100644 index 0000000..65322d0 --- /dev/null +++ b/FIRMWARE_NOTES.md @@ -0,0 +1,125 @@ +# Firmware Notes: ESP32 Весовой контроллер + +## Стек + +| Инструмент | Версия / примечание | +|----------------------|-----------------------------------------------------------------------------| +| Arduino IDE | Основная среда разработки | +| ESP32 core | **esp32 by Espressif Systems 3.x** (НЕ Arduino ESP32 Boards 2.0.x!) | +| Целевая плата | ESP32 Dev Module | +| Порт прошивки | USB Serial (напр. `/dev/cu.usbserial-...`) | + +> Использование Espressif 3.x принципиально: в нём есть нативная `ETH.h` с поддержкой W5500, +> которая надёжнее сторонней `Ethernet.h`. Версия 2.x (Arduino) вызывала `hardwareStatus: 0`. + +## Используемые библиотеки + +| Библиотека | Источник | Назначение | +|----------------------|-----------------------------|----------------------------------------| +| `ETH.h` | Встроена в ESP32 core 3.x | Ethernet W5500 через SPI (нативная) | +| `NetworkClient` | Встроена в ESP32 core 3.x | TCP-клиент поверх ETH.h | +| `NetworkUDP` | Встроена в ESP32 core 3.x | UDP для NTP-синхронизации | +| `PubSubClient` | Nick O'Leary (Arduino Lib) | MQTT клиент | +| `ArduinoJson` | Benoit Blanchon | Формирование JSON-payload | +| `Wire.h` | Встроена | I2C для DS3231 | +| `RTClib` | Adafruit | Работа с DS3231 RTC | + +> **Отказались от:** `Ethernet.h` (сторонняя) + `SSLClient` — SPI конфликты и TLS handshake failure. +> Переход на нативную `ETH.h` (Espressif) решил проблему. + +## Ключевые параметры конфигурации + +```cpp +// MQTT +const char* MQTT_SERVER = "77.222.43.248"; // scales.zeroday.su +const int MQTT_PORT = 1884; // plain (без TLS, тестовая фаза) +const char* MQTT_TOPIC = "scales/weighing/event"; +const char* DEVICE_ID = "scales_01"; +const char* MQTT_USER = "esp32"; +const char* MQTT_PASS = "Esp32Scales#2026"; + +// GPIO +#define W5500_CS_PIN 4 +#define W5500_RST_PIN 26 +#define RELAY_RED_PIN 32 +#define RELAY_GREEN_PIN 33 + +// UART (весы) +// Serial2, GPIO16 RX, GPIO17 TX, 9600 baud + +// SPI (W5500) — MOSI/MISO перепутаны на модуле +// SPI.begin(SCK=18, MISO=23, MOSI=19, SS=4) ← физически перевёрнуто! + +// NTP +// UDP broadcast на 216.239.35.0 (Google NTP) +``` + +## Логика основного цикла + +``` +BOOT: + 1. Инициализация DS3231 (I2C) — ОБЯЗАТЕЛЬНО до ETH.begin()! + 2. ETH.begin() — W5500 SPI инициализация + 3. DHCP → если FAIL → статический IP (192.168.10.200) + 4. NTP синхронизация RTC (UDP, Google 216.239.35.0) + 5. Serial2.begin(9600) — UART для весов + 6. Веб-сервер на порту 80 (live статус) + 7. MQTT connect (esp32 / Esp32Scales#2026) + +LOOP: + ├─ Читать Serial2 (строки с весов) + │ └─ Парсить: "ww018450.500kg" → weight_kg = 18450.5 + │ + ├─ Логика стабилизации: + │ ├─ Накапливаем N последних показаний + │ ├─ Если разброс < ±50 кг И вес > порога (машина есть) → stable = true + │ └─ Если stable → отправить MQTT + включить КРАСНЫЙ светофор + │ + ├─ После получения подтверждения взвешивания: + │ └─ Включить ЗЕЛЁНЫЙ светофор, сбросить флаг + │ + ├─ Ждать пока вес упадёт ниже порога → машина уехала → сбросить всё + │ + └─ MQTT reconnect при обрыве (rc != 0 → повторная попытка) + +WEB (встроенный HTTP): + GET / → live HTML дашборд (вес, статус светофора) + GET /api/status → JSON: {"weight_kg": ..., "stable": ..., "light": "red|green"} +``` + +## Логика светофора + +| Состояние | Красный | Зелёный | +|-----------------------|---------|---------| +| Ожидание машины | OFF | ON | +| Машина на весах | ON | OFF | +| Взвешивание стабильно | ON | OFF | +| Данные отправлены | OFF | ON | + +## Известные проблемы / TODO + +### Решённые проблемы + +- ✅ **GPIO5 strapping pin** — вызывал SPI конфликт при загрузке → переключено на GPIO4 +- ✅ **MOSI/MISO перепутаны** на зелёном W5500 модуле → компенсировано в `SPI.begin()` +- ✅ **Синий W5500 бракованный** — заменён на зелёный компактный 3.3V +- ✅ **DS3231 I2C конфликт с ETH** — решено инициализацией RTC до `ETH.begin()` +- ✅ **Ethernet.h + SSLClient не работали** → переход на нативную `ETH.h` (ESP32 core 3.x) +- ✅ **DHCP FAIL → Static IP** — добавлен fallback на 192.168.10.200 +- ✅ **NTP Timeout** — следствие отсутствия сети (теперь работает после решения W5500) + +### Актуальные TODO + +- [ ] **P5=3 на TITAN 9** — главный блокер. Нужен пароль сервисного меню (Zemic: +7 (472) 277-71-19) +- [ ] **Тест с подключённой платформой** — без платформы весы могут не давать RS232 +- [ ] **Переход на MQTTS** (порт 8883, TLS) после подтверждения RS232-потока +- [ ] **DS3231 detection нестабильный** — иногда не определяется при старте; возможно нужен pull-up +- [ ] **Локальная буферизация** — сохранять события если MQTT недоступен +- [ ] **Watchdog** — перезагрузка при зависании MQTT/Ethernet стека + +## Файлы прошивки + +Актуальный `.ino` файл находится **локально у Алексея** (не залит в репо). +Сгенерированный в ходе разработки скелет: `scales_controller.ino` (создавался в чате). + +Репозиторий бэкенда (server.js + WebSocket UI): https://git.zeroday.su/admin/scales diff --git a/HARDWARE.md b/HARDWARE.md new file mode 100644 index 0000000..0eb9c3f --- /dev/null +++ b/HARDWARE.md @@ -0,0 +1,119 @@ +# Hardware: Весовой контроллер на ESP32 + +## Используемые компоненты + +| Компонент | Примечание | +|----------------------------------|----------------------------------------------------------------------------------| +| ESP32-WROOM (ESP32 Dev Module) | Основной контроллер | +| W5500 Ethernet модуль | Зелёный компактный модуль 3.3V (синий оказался бракованным — см. ниже) | +| MAX3232 модуль | RS232 ↔ 3.3V TTL, питание 3–5В, 15×9 мм, рабочая t −40…+85°C | +| DS3231 RTC модуль | Часы реального времени с батарейкой; синхронизация NTP (Google 216.239.35.0) | +| 2-канальное реле (оптоизолятор) | На транзисторах BC547, управление светофором (красный / зелёный) | +| Блок питания 5В 2А | Питание всей схемы | +| Zemic TITAN 9 (весовой индикатор)| Основан на Zemic A12E; разъём DB25 (RS-232); весовая платформа до 50–60 т | + +> **Важно:** Синий W5500 (первый заказанный) оказался бракованным — RJ45-трансформатор не работал +> несмотря на горящий светодиод питания. Заменён на зелёный компактный модуль 3.3V. + +## Схема подключения + +### W5500 → ESP32 (SPI) + +``` +W5500 ESP32 +----- ----- +MOSI → GPIO23 +MISO → GPIO19 ⚠️ MOSI/MISO на модуле подписаны наоборот — +SCK → GPIO18 в прошивке SPI.begin(18, 23, 19, 4) — переставлены! +CS → GPIO4 ⚠️ GPIO5 — strapping pin, вызывает конфликт SPI при старте +RST → GPIO26 используем GPIO4 +3.3V → 3.3V +GND → GND +``` + +### MAX3232 → ESP32 (UART RS232) + +``` +Весы DB25 MAX3232 (RS232 side) MAX3232 (TTL side) ESP32 +--------- ------------------ ------------------ ----- +Pin 2 TXD → RX (RS232) + TX (TTL) → GPIO16 (RX2) +Pin 7 GND → GND GND + VCC (3.3V) ← 3.3V +``` + +> Весы DB25: передача данных только на TXD + GND — 2 провода минимум. +> RXD нужен только если отправлять команды (T — тара, Z — обнуление, R — запрос веса). +> DTR может использоваться для питания гальваноразвязки (уточнить по конкретному экземпляру). + +### Реле → ESP32 (светофор) + +``` +ESP32 Схема Нагрузка +----- ----- -------- +GPIO32 → 1 кОм → база BC547 → коллектор → реле К1 → КРАСНЫЙ сигнал +GPIO33 → 1 кОм → база BC547 → коллектор → реле К2 → ЗЕЛЁНЫЙ сигнал +GND → эмиттер BC547 +5V → обмотка реле (через диод защиты 1N4007) +``` + +### DS3231 → ESP32 (I2C) + +``` +DS3231 ESP32 +------ ----- +SDA → GPIO21 +SCL → GPIO22 +VCC → 3.3V +GND → GND +``` + +> **Порядок инициализации:** DS3231 должен инициализироваться **до** вызова `ETH.begin()`, +> иначе возникает конфликт I2C. + +### Полная карта GPIO + +| GPIO | Функция | +|------|----------------------| +| 4 | W5500 CS (SPI) | +| 16 | RS232 RX (Serial2) | +| 17 | RS232 TX (Serial2) | +| 18 | W5500 SCK | +| 19 | W5500 MISO | +| 21 | DS3231 SDA (I2C) | +| 22 | DS3231 SCL (I2C) | +| 23 | W5500 MOSI | +| 26 | W5500 RST | +| 32 | Реле КРАСНЫЙ | +| 33 | Реле ЗЕЛЁНЫЙ | + +## Питание + +- Общий источник: **5В 2А** (блок питания) +- ESP32 питается через USB/VIN от 5В +- W5500: **3.3V** (зелёный модуль имеет встроенный стабилизатор, но питается от 3.3V напрямую) +- MAX3232: 3.3V от ESP32 +- DS3231: 3.3V от ESP32 + CR2032 батарейка для хранения времени +- Реле: 5В обмотка через BC547 (логика 3.3V с ESP32 управляет через транзистор) + +## Корпус / монтаж + +Монтаж предполагается в техническом отсеке на объекте рядом с весовым индикатором TITAN 9. +Корпус и способ крепления — TBD (на усмотрение Алексея на месте). + +## Калибровка датчиков + +Весовой индикатор TITAN 9 используется как готовый прибор — **калибровка датчиков выполняется +внутри индикатора**, не на стороне ESP32. ESP32 только принимает уже откалиброванные данные по RS232. + +Параметры индикатора (настраиваются через сервисное меню с паролем): + +| Параметр | Назначение | Нужное значение | +|----------|------------------------------------|------------------------| +| P3 | Скорость порта | 1 = 9600 baud | +| P4 | Что передавать | 2 = брутто | +| P5 | Режим передачи | **3 = при стабилизации** | + +> ⚠️ **Текущий статус:** P5 стоит в режиме "нет передачи" (заводской дефолт). +> Для входа в сервисное меню нужен пароль — уточнить у Zemic: **+7 (472) 277-71-19**. +> Тест без подключённой платформы не даст RS232-вывода даже при правильном P5. diff --git a/INDEX.md b/INDEX.md new file mode 100644 index 0000000..aadd817 --- /dev/null +++ b/INDEX.md @@ -0,0 +1,74 @@ +# INDEX: Весовой контроллер — Gitea Backup + +Репозиторий: https://git.zeroday.su/admin/weighing-controller +Автор: Алексей (ffr) +Дата бэкапа: 2026-04-30 +Источник: чаты Claude.ai (проект «Весовой контроллер») + +--- + +## Что собрано и куда + +| Файл | Содержимое | +|-----------------------|----------------------------------------------------------------------------------| +| `PROTOCOL.md` | Топология, JSON-схема, MQTT топик/QoS, авторизация, retry-логика | +| `HARDWARE.md` | Компоненты, схема подключения (ASCII), GPIO карта, питание, калибровка | +| `FIRMWARE_NOTES.md` | Стек (ESP32 core 3.x), библиотеки, логика цикла, известные проблемы, TODO | +| `INDEX.md` | Этот файл — навигация по проекту | + +--- + +## Чего не хватает + +### Прошивка (главное) +- **`scales_controller.ino`** — актуальный файл прошивки **лежит локально у Алексея**. + Создавался итеративно в чате, последняя версия включает: + - `ETH.h` (нативная, ESP32 core 3.x) + - PubSubClient MQTT с авторизацией + - Serial2 для RS232 (GPIO16/17) + - DS3231 RTC + - Светофорное реле (GPIO32/33) + - Встроенный HTTP-сервер + - Нужно залить в этот репо! + +### Схема (KiCad / Fritzing) +- Полная принципиальная схема не рисовалась — есть только текстовое описание в `HARDWARE.md` +- TODO: нарисовать схему + +### Конфиг сервера +- `server.js`, `package.json`, nginx конфиг, Mosquitto `acs.conf` — лежат в **отдельном репо**: + 👉 https://git.zeroday.su/admin/scales + +### Документация на весы +- Zemic A12E / TITAN 9 datasheet — найден в сети, не сохранён в репо + PDF: `https://vial.by/pdf/zemic/Texnicheskaia_instrukcia___Zemic%2012E.pdf` + +--- + +## Текущий статус проекта (на 2026-04-30) + +**Готово:** +- ✅ ESP32 инициализирует W5500, получает IP, подключается к MQTT (plain, порт 1884) +- ✅ Сервер https://scales.zeroday.su — live, real-time WebSocket дашборд, история взвешиваний +- ✅ Mosquitto с авторизацией (анонимный доступ запрещён) +- ✅ DS3231 RTC работает, синхронизируется с NTP + +**Главный блокер:** +- ⛔ TITAN 9 не передаёт RS232 — P5 в дефолтном режиме "нет передачи" +- Нужен пароль для входа в сервисное меню → **позвонить Zemic: +7 (472) 277-71-19** +- После установки P5=3 — выехать на объект с подключённой платформой для финального теста + +**Следующий шаг:** +1. Звонок в Zemic → получить навигацию по меню и пароль +2. Выезд на объект, подключить ESP32 к весам с платформой +3. Убедиться что данные идут в топик `scales/weighing/event` +4. Перейти на MQTTS (порт 8883) + +--- + +## Ссылки + +- Бэкенд (server.js + UI): https://git.zeroday.su/admin/scales +- Live дашборд: https://scales.zeroday.su +- Zemic A12E PDF: https://vial.by/pdf/zemic/Texnicheskaia_instrukcia___Zemic%2012E.pdf +- Zemic техподдержка: +7 (472) 277-71-19 diff --git a/PROTOCOL.md b/PROTOCOL.md new file mode 100644 index 0000000..ba7a4ef --- /dev/null +++ b/PROTOCOL.md @@ -0,0 +1,103 @@ +# Протокол передачи данных с весов на сервер + +## Топология + +``` +Zemic TITAN 9 (RS232/DB25) + ↓ TXD + GND (3-4 провода) + MAX3232 (RS232 ↔ 3.3V TTL) + ↓ UART TTL + ESP32 (GPIO16/RX2) + ↓ SPI + W5500 Ethernet модуль + ↓ TCP/IP (LAN) + Mosquitto MQTT Broker (порт 1884 plain / 8883 MQTTS — в планах) + ↓ подписчик + Node.js / server.js (порт 3016, PM2) + ↓ WebSocket + Web UI (https://scales.zeroday.su) +``` + +## Формат сообщения (JSON-схема) + +Топик: `scales/weighing/event` + +```json +{ + "device_id": "scales_01", + "timestamp": "2026-03-01T10:23:45Z", + "weight_kg": 18450.5, + "weight_raw": "ww018450.500kg", + "stable": true, + "plate": null +} +``` + +| Поле | Тип | Описание | +|-------------|---------|-------------------------------------------------------------| +| device_id | string | Идентификатор контроллера (если весов несколько) | +| timestamp | string | ISO 8601, UTC. Берётся с DS3231 RTC (синхронизируется NTP) | +| weight_kg | float | Распарсенный вес в кг (удобно для БД) | +| weight_raw | string | Сырая строка с весов (`ww000.000kg`) | +| stable | bool | true = вес стабилизировался перед отправкой | +| plate | null | Зарезервировано — номер авто добавляет внешняя АСУ | + +### Формат строки с весов (Zemic A12E / TITAN 9) + +``` +ww000.000kg — вес брутто +wn000.000kg — вес нетто +wt000.000kg — вес тары +``` + +ASCII, 1 стартовый бит, 8 бит данных, 1 стоповый бит. Скорость — P3 (9600 по умолчанию). + +## MQTT-топик и QoS + +| Параметр | Значение | +|---------------|----------------------------| +| Топик | `scales/weighing/event` | +| QoS | 1 (at least once) | +| Retain | false | +| Брокер | Mosquitto на scales.zeroday.su | +| Порт (plain) | 1884 (для тестовой фазы) | +| Порт (TLS) | 8883 (планируется) | + +## Аутентификация / TLS / credentials + +Анонимный доступ к брокеру **запрещён** (`allow_anonymous false`). + +| Пользователь | Пароль | Роль | +|----------------|--------------------|-------------------------------| +| esp32 | Esp32Scales#2026 | ESP32 контроллер (publisher) | +| scales-server | ScalesServer#2026 | Node.js backend (subscriber) | + +Конфиг Mosquitto: `/etc/mosquitto/conf.d/acs.conf` +Файл паролей: `/etc/mosquitto/passwd` + +TLS (MQTTS port 8883) — **запланировано** после подтверждения RS232-потока. + +## Логика стабилизации и retry + +### На стороне ESP32 (firmware) + +Весы настроены на P5=3 (передача только при стабильном весе) — т.е. строка приходит уже стабильная. +Дополнительная логика на ESP32: + +1. Читаем строку каждые ~500 мс с Serial2 +2. Если последние 5–10 показаний отличаются не более чем на ±20–50 кг — считаем вес стабильным +3. Отправляем MQTT-событие **один раз** +4. Ждём пока вес упадёт ниже порога (машина уехала) → сбрасываем флаг +5. Готовы к следующему взвешиванию + +### Retry при обрыве MQTT + +- При `rc=-2` (не удалось подключиться) — ESP32 делает повторную попытку каждые N секунд +- Данные не буферизуются локально (TODO: добавить очередь на случай длительного обрыва) + +## Текущие ограничения / TODO по протоколу + +- [ ] MQTTS (порт 8883) — включить после подтверждения RS232 +- [ ] Локальная очередь на ESP32 при обрыве связи +- [ ] Поле `plate` — заполняется внешней АСУ распознавания номеров +- [ ] Подтвердить навигацию в меню TITAN 9 для выставления P5=3 (контакт: Zemic +7 (472) 277-71-19) diff --git a/README.md b/README.md new file mode 100644 index 0000000..5c45b2b --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +# Весовой контроллер — ESP32 + +ESP32-контроллер для автомобильных весов (грузовые весы, TITAN 9 / Zemic A12E). +Получает данные с весового терминала по RS232 → отправляет в MQTT → сервер записывает и транслирует в WebSocket-дашборд. + +## ⛔ Текущий блокер + +**TITAN 9 не передаёт данные по RS232** — параметр P5 в дефолтном режиме «нет передачи». +Нужен пароль для сервисного меню → **позвонить Zemic: +7 (472) 277-71-19** +После P5=3 → выезд на объект → финальный тест. + +## Навигация + +| Файл | Содержимое | +|------|------------| +| [`PROTOCOL.md`](PROTOCOL.md) | Топология, JSON-схема, MQTT-топик, QoS, авторизация, retry | +| [`HARDWARE.md`](HARDWARE.md) | Компоненты, GPIO карта, ASCII-схема, питание, калибровка | +| [`FIRMWARE_NOTES.md`](FIRMWARE_NOTES.md) | Стек (ESP32 core 3.x), библиотеки, логика цикла, known issues | +| [`INDEX.md`](INDEX.md) | Манифест: что есть, чего нет, ссылки | + +## ⚠️ Файлы не в репо + +- **`scales_controller.ino`** — актуальная прошивка **лежит локально у Алексея** (создавалась итеративно в чатах). + Стек: ESP32 core 3.x, `ETH.h`, PubSubClient, Serial2 RS232, DS3231 RTC, реле GPIO32/33, HTTP-сервер. + **Залей через: `firmware/scales_controller.ino`** + +## Связанные репо + +- 🖥️ **[admin/scales](https://git.zeroday.su/admin/scales)** — Node.js сервер (`server.js`), WebSocket UI, Mosquitto config + Live: https://scales.zeroday.su + +## Ресурсы + +- Zemic A12E PDF: https://vial.by/pdf/zemic/Texnicheskaia_instrukcia___Zemic%2012E.pdf +- Zemic тех.поддержка: +7 (472) 277-71-19 diff --git a/firmware/.gitkeep b/firmware/.gitkeep new file mode 100644 index 0000000..cb5968b --- /dev/null +++ b/firmware/.gitkeep @@ -0,0 +1,2 @@ +# Положи сюда: scales_controller.ino +# (актуальная прошивка с ESP32 core 3.x, PubSubClient, Serial2, DS3231, ETH.h)