+move
This commit is contained in:
@@ -0,0 +1,88 @@
|
|||||||
|
# LD2410B Conveyor Counter
|
||||||
|
|
||||||
|
ESPHome прошивка для подсчета товаров на конвейере с помощью mmWave сенсора **Hi-Link LD2410B** + **ESP32**. Данные передаются через **MQTT**.
|
||||||
|
|
||||||
|
## Схема подключения
|
||||||
|
|
||||||
|
```
|
||||||
|
ESP32 DevKit V1 LD2410B
|
||||||
|
──────────────────────────────────
|
||||||
|
GPIO17 (TX) ────► RX
|
||||||
|
GPIO16 (RX) ────► TX
|
||||||
|
GPIO18 ────► OUT (digital motion)
|
||||||
|
3.3V / 5V ────► VCC
|
||||||
|
GND ────► GND
|
||||||
|
GPIO2 ────► LED (status, onboard)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Важно:** Питание LD2410B — **5V** (не 3.3V!). UART логика 3.3V — совместима с ESP32.
|
||||||
|
|
||||||
|
## Как работает
|
||||||
|
|
||||||
|
1. **UART** (256000 baud) — чтение дистанции и энергии движения для каждой "зоны" (gate)
|
||||||
|
2. **GPIO OUT** — быстрый бинарный сигнал присутствия
|
||||||
|
3. **Конечный автомат** определяет момент прохода товара:
|
||||||
|
- `State 0` — ожидание
|
||||||
|
- `State 1` — товар в зоне (energy > threshold)
|
||||||
|
- `State 2` — товар прошел (debounce 300ms) → +1 к счетчику
|
||||||
|
|
||||||
|
## MQTT топики
|
||||||
|
|
||||||
|
| Топик | Описание |
|
||||||
|
|---|---|
|
||||||
|
| `ld2410b/conveyor/sensor/items_count/state` | Общий счетчик товаров |
|
||||||
|
| `ld2410b/conveyor/sensor/moving_distance/state` | Дистанция до цели (cm) |
|
||||||
|
| `ld2410b/conveyor/sensor/trigger_distance/state` | Дистанция в зоне детекции |
|
||||||
|
| `ld2410b/conveyor/text_sensor/counter_status/state` | Строка статуса (state, energy, count) |
|
||||||
|
| `ld2410b/conveyor/button/reset_counter/command` | Сброс счетчика (payload: любая) |
|
||||||
|
| `ld2410b/conveyor/number/energy_threshold/command` | Порог энергии детекции |
|
||||||
|
| `ld2410b/conveyor/number/min_distance_cm/command` | Мин. дистанция зоны (cm) |
|
||||||
|
| `ld2410b/conveyor/number/max_distance_cm/command` | Макс. дистанция зоны (cm) |
|
||||||
|
|
||||||
|
## Настройка порогов
|
||||||
|
|
||||||
|
### Energy Threshold
|
||||||
|
- **По умолчанию:** 50
|
||||||
|
- **Диапазон:** 10–100
|
||||||
|
- Чем выше — тем меньше ложных срабатываний, но нужно больше энергии движения для детекции
|
||||||
|
|
||||||
|
### Min / Max Distance
|
||||||
|
- **По умолчанию:** 75–200 см
|
||||||
|
- Установите диапазон, в котором товары проходят через луч
|
||||||
|
- LD2410B имеет минимальную дистанцию ~75 см (gate 0)
|
||||||
|
|
||||||
|
## Установка
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Установите ESPHome
|
||||||
|
pip install esphome
|
||||||
|
|
||||||
|
# Скомпилируйте и залейте
|
||||||
|
esphome run ld2410b_counter.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
## secrets.yaml
|
||||||
|
|
||||||
|
Создайте файл `secrets.yaml` рядом с конфигом:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
mqtt_broker: "192.168.1.100"
|
||||||
|
mqtt_user: "esphome"
|
||||||
|
mqtt_pass: "your_password"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Отладка
|
||||||
|
|
||||||
|
1. Откройте веб-интерфейс ESP (по IP устройства)
|
||||||
|
2. Следите за `Counter Status` — строка вида `State: 1 | E: 65 | D: 120 | Count: 42`
|
||||||
|
3. Если счетчик не увеличивается:
|
||||||
|
- Уменьшите `Energy Threshold`
|
||||||
|
- Проверьте что товар попадает в диапазон `Min/Max Distance`
|
||||||
|
4. Если ложные срабатывания — увеличьте `Energy Threshold` или сузьте диапазон дистанций
|
||||||
|
|
||||||
|
## Ограничения LD2410B
|
||||||
|
|
||||||
|
- **Минимальная дистанция:** ~75 см
|
||||||
|
- **Угол обзора:** ~120° (для сужения используйте физический экран/тубус перед сенсором)
|
||||||
|
- **Не различает** направление движения (для этого нужен LD2450 с трекингом X/Y)
|
||||||
|
- **Макс. скорость конвейера:** зависит от размера товаров и debounce (300ms). Для быстрого конвейера уменьшите debounce в коде.
|
||||||
@@ -0,0 +1,235 @@
|
|||||||
|
esphome:
|
||||||
|
name: ld2410b-counter
|
||||||
|
friendly_name: "LD2410B Conveyor Counter"
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
board: esp32dev
|
||||||
|
framework:
|
||||||
|
type: arduino
|
||||||
|
|
||||||
|
# Подключение LD2410B по UART
|
||||||
|
uart:
|
||||||
|
tx_pin: GPIO17
|
||||||
|
rx_pin: GPIO16
|
||||||
|
baud_rate: 256000
|
||||||
|
parity: NONE
|
||||||
|
stop_bits: 1
|
||||||
|
|
||||||
|
# GPIO OUT пин для быстрого детектирования движения
|
||||||
|
binary_sensor:
|
||||||
|
- platform: gpio
|
||||||
|
pin: GPIO18
|
||||||
|
name: "LD2410B Motion GPIO"
|
||||||
|
id: motion_gpio
|
||||||
|
device_class: motion
|
||||||
|
internal: true
|
||||||
|
|
||||||
|
ld2410:
|
||||||
|
|
||||||
|
sensor:
|
||||||
|
# Дистанция до движущейся цели
|
||||||
|
- platform: ld2410
|
||||||
|
moving_distance:
|
||||||
|
name: "Moving Distance"
|
||||||
|
id: moving_dist
|
||||||
|
|
||||||
|
# Дистанция до неподвижной цели
|
||||||
|
- platform: ld2410
|
||||||
|
still_distance:
|
||||||
|
name: "Still Distance"
|
||||||
|
id: still_dist
|
||||||
|
|
||||||
|
# Энергия движения в зоне 0 (ближняя зона, 0.75-1.5м)
|
||||||
|
- platform: ld2410
|
||||||
|
g0:
|
||||||
|
move_energy:
|
||||||
|
name: "Gate 0 Move Energy"
|
||||||
|
id: g0_energy
|
||||||
|
internal: true
|
||||||
|
still_energy:
|
||||||
|
name: "Gate 0 Still Energy"
|
||||||
|
id: g0_still
|
||||||
|
internal: true
|
||||||
|
|
||||||
|
# Энергия движения в зоне 1 (1.5-2.25м)
|
||||||
|
- platform: ld2410
|
||||||
|
g1:
|
||||||
|
move_energy:
|
||||||
|
name: "Gate 1 Move Energy"
|
||||||
|
id: g1_energy
|
||||||
|
internal: true
|
||||||
|
|
||||||
|
# Счетчик прошедших товаров
|
||||||
|
- platform: template
|
||||||
|
name: "Items Count"
|
||||||
|
id: items_count
|
||||||
|
icon: "mdi:counter"
|
||||||
|
unit_of_measurement: "items"
|
||||||
|
accuracy_decimals: 0
|
||||||
|
state_class: total_increasing
|
||||||
|
device_class: count
|
||||||
|
|
||||||
|
# Дистанция срабатывания (для отладки)
|
||||||
|
- platform: template
|
||||||
|
name: "Trigger Distance"
|
||||||
|
id: trigger_dist
|
||||||
|
icon: "mdi:ruler"
|
||||||
|
unit_of_measurement: "cm"
|
||||||
|
accuracy_decimals: 0
|
||||||
|
update_interval: 0.5s
|
||||||
|
|
||||||
|
# MQTT
|
||||||
|
mqtt:
|
||||||
|
broker: !secret mqtt_broker
|
||||||
|
username: !secret mqtt_user
|
||||||
|
password: !secret mqtt_pass
|
||||||
|
topic_prefix: ld2410b/conveyor
|
||||||
|
|
||||||
|
# Глобальные переменные для логики подсчета
|
||||||
|
globals:
|
||||||
|
- id: item_count_total
|
||||||
|
type: int
|
||||||
|
restore_value: true
|
||||||
|
initial_value: "0"
|
||||||
|
|
||||||
|
- id: item_state
|
||||||
|
type: int
|
||||||
|
restore_value: no
|
||||||
|
initial_value: "0"
|
||||||
|
|
||||||
|
- id: last_trigger_time
|
||||||
|
type: unsigned long
|
||||||
|
restore_value: no
|
||||||
|
initial_value: "0"
|
||||||
|
|
||||||
|
- id: energy_threshold
|
||||||
|
type: float
|
||||||
|
restore_value: no
|
||||||
|
initial_value: "50.0"
|
||||||
|
|
||||||
|
- id: distance_min_cm
|
||||||
|
type: float
|
||||||
|
restore_value: no
|
||||||
|
initial_value: "75.0"
|
||||||
|
|
||||||
|
- id: distance_max_cm
|
||||||
|
type: float
|
||||||
|
restore_value: no
|
||||||
|
initial_value: "200.0"
|
||||||
|
|
||||||
|
text_sensor:
|
||||||
|
# Статус счетчика
|
||||||
|
- platform: template
|
||||||
|
name: "Counter Status"
|
||||||
|
id: counter_status
|
||||||
|
icon: "mdi:information"
|
||||||
|
update_interval: 1s
|
||||||
|
|
||||||
|
# Кнопки управления
|
||||||
|
button:
|
||||||
|
- platform: template
|
||||||
|
name: "Reset Counter"
|
||||||
|
id: reset_counter
|
||||||
|
on_press:
|
||||||
|
- lambda: |-
|
||||||
|
id(item_count_total) = 0;
|
||||||
|
id(items_count).publish_state(0);
|
||||||
|
|
||||||
|
# Number для настройки порогов из Home Assistant / MQTT
|
||||||
|
number:
|
||||||
|
- platform: template
|
||||||
|
name: "Energy Threshold"
|
||||||
|
id: energy_threshold_ui
|
||||||
|
min_value: 10
|
||||||
|
max_value: 100
|
||||||
|
step: 5
|
||||||
|
initial_value: 50
|
||||||
|
set_action:
|
||||||
|
- lambda: id(energy_threshold) = x;
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: "Min Distance (cm)"
|
||||||
|
id: dist_min_ui
|
||||||
|
min_value: 50
|
||||||
|
max_value: 150
|
||||||
|
step: 5
|
||||||
|
initial_value: 75
|
||||||
|
set_action:
|
||||||
|
- lambda: id(distance_min_cm) = x;
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: "Max Distance (cm)"
|
||||||
|
id: dist_max_ui
|
||||||
|
min_value: 100
|
||||||
|
max_value: 500
|
||||||
|
step: 10
|
||||||
|
initial_value: 200
|
||||||
|
set_action:
|
||||||
|
- lambda: id(distance_max_cm) = x;
|
||||||
|
|
||||||
|
# Основной цикл подсчета + статус
|
||||||
|
interval:
|
||||||
|
- interval: 50ms
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
// Получаем текущие значения
|
||||||
|
float energy = id(g0_energy).state;
|
||||||
|
float dist = id(moving_dist).state;
|
||||||
|
|
||||||
|
// Проверка валидности дистанции
|
||||||
|
bool valid_dist = (dist >= id(distance_min_cm)) && (dist <= id(distance_max_cm));
|
||||||
|
|
||||||
|
// Обновляем отладочный сенсор дистанции
|
||||||
|
id(trigger_dist).publish_state(valid_dist ? dist : 0);
|
||||||
|
|
||||||
|
// Конечный автомат: 0 = ожидание, 1 = объект в зоне, 2 = debounce после прохода
|
||||||
|
unsigned long now = millis();
|
||||||
|
int current_state = id(item_state);
|
||||||
|
|
||||||
|
// Объект вошел в зону (энергия выше порога + дистанция в пределах)
|
||||||
|
if (current_state == 0 && energy > id(energy_threshold) && valid_dist) {
|
||||||
|
id(item_state) = 1;
|
||||||
|
id(last_trigger_time) = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Объект ушел из зоны — инкремент счетчика
|
||||||
|
if (current_state == 1 && energy < (id(energy_threshold) * 0.5)) {
|
||||||
|
id(item_state) = 2;
|
||||||
|
id(item_count_total)++;
|
||||||
|
id(items_count).publish_state(id(item_count_total));
|
||||||
|
id(last_trigger_time) = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debounce: ждем 300мс после прохода перед новым детектом
|
||||||
|
if (current_state == 2 && (now - id(last_trigger_time)) > 300) {
|
||||||
|
id(item_state) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Сброс stuck состояния (объект "завис" в зоне больше 5 сек)
|
||||||
|
if (current_state == 1 && (now - id(last_trigger_time)) > 5000) {
|
||||||
|
id(item_state) = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
- interval: 1s
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
std::string status = "State: " + std::to_string(id(item_state)) +
|
||||||
|
" | E: " + std::to_string(id(g0_energy).state, 0) +
|
||||||
|
" | D: " + std::to_string(id(moving_dist).state, 0) +
|
||||||
|
" | Count: " + std::to_string(id(item_count_total));
|
||||||
|
id(counter_status).publish_state(status.c_str());
|
||||||
|
|
||||||
|
# Светодиод статуса (GPIO2 на ESP32 devkit)
|
||||||
|
output:
|
||||||
|
- platform: gpio
|
||||||
|
pin: GPIO2
|
||||||
|
id: status_led
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: binary
|
||||||
|
id: led_status
|
||||||
|
output: status_led
|
||||||
|
internal: true
|
||||||
|
|
||||||
|
logger:
|
||||||
|
level: INFO
|
||||||
Reference in New Issue
Block a user