Калибровка: определение времени полного хода привода
Введение в калибровку приводов
В современных системах автоматизации мы часто сталкиваемся с исполнительными механизмами, которые не предоставляют точной информации о своем текущем положении. К таким устройствам относятся приводы рулонных штор, роллет, гаражных ворот или некоторых типов клапанов. В отличие от сервоприводов с абсолютными энкодерами, которые всегда "знают" свою позицию, эти более простые и распространенные механизмы управляются подачей питания для движения в одном из двух направлений: 'Открыть' или 'Закрыть'. Как же в таком случае реализовать команду "открыть штору на 50%"?
Ответ кроется в процедуре калибровки. Поскольку у нас нет прямого способа измерить положение, мы используем единственный доступный нам параметр — время. Идея проста: если мы знаем, сколько времени требуется приводу для перемещения из одного крайнего положения в другое, мы можем с высокой точностью управлять его промежуточными состояниями.
> 📋 Ключевые понятия:
> * Калибровка привода: Процесс измерения и сохранения временных характеристик работы механизма для последующего точного управления его положением.
> * Время полного хода (ВПХ): Фундаментальный параметр, представляющий собой время в миллисекундах, необходимое приводу для полного перемещения из положения "Полностью закрыто" в положение "Полностью открыто" (или наоборот).
Цель данного урока — научиться измерять, автоматически вычислять и надежно сохранять ВПХ для приводов с реверсивным двигателем с помощью контроллера HI и среды Node-RED. Этот процесс является обязательным подготовительным этапом для реализации сценариев позиционирования, например, «Установить жалюзи на 75%» или «Приоткрыть ворота для проветривания». Без точного значения ВПХ любая попытка процентного управления будет основана на догадках и приведет к накоплению ошибки с каждым циклом работы.
Мы рассмотрим как ручной метод замера, который поможет понять физику процесса, так и создание полностью автоматического сценария калибровки, который может быть запущен инсталлятором на объекте или даже удаленно.
---
Ручной замер ВПХ: основа для автоматизации
Прежде чем приступать к автоматизации, крайне важно провести замер времени полного хода вручную. Этот процесс не только дает нам базовое значение для последующей проверки, но и позволяет убедиться в корректной работе механики привода и концевых выключателей.
Для ручного замера нам потребуется простейший сценарий в Node-RED, который будет выполнять роль удобного секундомера, а также интерфейс для ручного управления приводом (например, из предыдущих уроков).
Пошаговая инструкция по ручному замеру
Вам понадобятся всего два узла: `inject` и `debug`. Узел `inject` по умолчанию отправляет текущую временную метку (timestamp).
* Создайте узел `inject` с `payload` = `timestamp`.
* Соедините его с узлом `debug`.
* Разверните (Deploy) сценарий. Каждое нажатие на кнопку узла `inject` будет выводить в панель отладки точное время в формате Unix.
С помощью вашего сценария управления (или временных кнопок) отправьте команду "Закрыть". Дождитесь, пока привод полностью закроется. Вы должны услышать характерный щелчок встроенного концевого выключателя (Limit Switch) или увидеть сигнал от него, как мы рассматривали в уроке `COURSE-05-M06-L03`. Это гарантирует, что мы начинаем движение из положения 0%.
* Приготовьтесь одновременно нажать на кнопку нашего "секундомера" (`inject`) и подать команду "Открыть" на привод.
* Нажмите обе кнопки. В панели `debug` появится первая временная метка.
* Внимательно следите за приводом. Как только он достигнет крайнего открытого положения и остановится (сработает второй концевой выключатель), немедленно нажмите на кнопку "секундомера" еще раз.
* В панели `debug` появится вторая временная метка. Разница между второй и первой метками и есть измеренное время полного хода.
Пример расчета:
* Первая метка (старт): `1678886401000`
* Вторая метка (финиш): `1678886423500`
* ВПХ = `1678886423500` - `1678886401000` = `22500` миллисекунд, или 22.5 секунды.
Теперь повторите шаг 3, но для движения из положения "Полностью открыто" в положение "Полностью закрыто".
Проведите замеры как минимум 2-3 раза в каждом направлении. Значения могут незначительно отличаться из-за особенностей механики (например, движение вверх под действием силы тяжести может быть чуть быстрее, чем вниз). Вычислите среднее значение. Например:
* Закрытие -> Открытие: 22.5 с, 22.6 с, 22.4 с (среднее: 22.5 с)
* Открытие -> Закрытие: 22.8 с, 22.7 с, 22.8 с (среднее: 22.76 с)
В качестве итогового ВПХ можно взять большее из двух средних значений. Это гарантирует, что привод всегда успеет дойти до крайнего положения. В нашем случае, мы бы взяли `22760` миллисекунд.
Этот простой ручной процесс закладывает основу для понимания логики автоматической калибровки. Мы убедились, что концевые выключатели работают, и получили эталонное значение, с которым будем сравнивать результаты работы нашего автоматического сценария.
---
Сценарий автоматической калибровки в Node-RED
Ручной замер хорош для первоначальной оценки, но для production-ready системы нам нужен автоматизированный, повторяемый и точный процесс. Создадим сценарий, который будет выполнять калибровку по одной команде.
> 💡 Подсказка: Для хранения калибровочных значений используйте контекст с типом хранилища `file`. Это гарантирует, что данные не будут потеряны после перезагрузки или сбоя питания контроллера HI. Настроить это можно в файле `settings.js` вашего Node-RED.
Логика автоматического сценария
Алгоритм работы сценария будет следующим:
Реализация в Node-RED
Для реализации нам понадобятся узлы для отслеживания сигналов с концевых выключателей (например, `rpi gpio in`), узлы для управления реле (`rpi gpio out`), а также узлы для реализации логики.
Пример потока (Flow):// Запуск калибровки
[Inject: Start Calib.] --> [Function: Init & Close] --> [Relay Out: Close]
// Отслеживание концевиков
[Limit SW In: Close] --> [rbe] --+
|
[Limit SW In: Open] --> [rbe] --+--> [Function: Calibration Logic] --+--> [Debug: Result]
|
+--> [Relay Out: Open]
+--> [Relay Out: Stop]
Настройка узлов:
// Получаем состояние калибровки из контекста потока
let state = flow.get('calibration_state') || 'idle';
const topic = msg.topic;
// Если пришла команда на запуск калибровки
if (msg.payload && msg.payload.command === 'start_calibration' && state === 'idle') {
node.warn('Запуск автоматической калибровки...');
flow.set('calibration_state', 'moving_to_close');
node.status({fill:"yellow", shape:"ring", text:"Движение к 0%..."});
// Возвращаем сообщение для запуска движения на закрытие
// Это сообщение пойдет на узел управления реле 'Close'
return { payload: 1, topic: 'relay/close' };
}
// Машина состояний (State Machine) для процесса калибровки
switch (state) {
case 'moving_to_close':
// Мы двигались на закрытие и сработал концевик 'Закрыто'
if (topic === 'limitswitch/close' && msg.payload == 1) {
node.warn('Достигнуто положение "Закрыто". Начинаем замер ВПХ.');
// 1. Сохраняем время старта
flow.set('start_ts', Date.now());
// 2. Меняем состояние
flow.set('calibration_state', 'measuring');
node.status({fill:"blue", shape:"dot", text:"Идет замер..."});
// 3. Возвращаем сообщение для запуска движения на открытие
return { payload: 1, topic: 'relay/open' };
}
break;
case 'measuring':
// Мы замеряли время и сработал концевик 'Открыто'
if (topic === 'limitswitch/open' && msg.payload == 1) {
const startTime = flow.get('start_ts');
const endTime = Date.now();
const travelTime = endTime - startTime;
node.warn(`Замер ВПХ завершен. Результат: ${travelTime} мс.`);
// 1. Сохраняем результат в персистентный контекст
// 'file' указывает на хранение в файловой системе контроллера
flow.set('full_travel_time_ms', travelTime, 'file');
// 2. Сбрасываем состояние и останавливаем привод
flow.set('calibration_state', 'idle');
node.status({fill:"green", shape:"dot", text:`Готово: ${travelTime} мс`});
// 3. Возвращаем два сообщения: одно с результатом, другое для остановки
const resultMsg = {
topic: "calibration/result",
payload: {
status: "success",
value_ms: travelTime
}
};
const stopMsg = { payload: 0, topic: 'relay/stop' }; // Останавливаем все реле
return [resultMsg, stopMsg];
}
break;
}
// В остальных случаях ничего не делаем
return null;
Теперь, после развертывания этого потока, однократное нажатие на кнопку `Inject` запустит полный цикл: штора закроется, затем откроется, а в контексте `flow.full_travel_time_ms` будет сохранено точное время полного хода.
---
Обработка и хранение калибровочного значения
Получить "сырое" значение ВПХ — это только половина дела. Чтобы система была по-настоящему надежной и отказоустойчивой (production-ready), это значение нужно правильно обработать и сохранить.
> ⚠️ Внимание: Не используйте измеренное время 'миллисекунда в миллисекунду'. Всегда добавляйте запас в 5-10% для компенсации возможных изменений в скорости работы привода или механического сопротивления. Это гарантирует, что привод всегда достигнет конечного положения, даже если напряжение в сети немного "просело" или механизм со временем стал двигаться туже.
Добавление запаса времени (Safety Margin)
Измеренное значение `travelTime` — это идеальное время в текущих условиях. Однако условия меняются. Чтобы команда "Открыть на 100%" гарантированно приводила к срабатыванию концевого выключателя, а не останавливала привод в 1 см от него, мы вводим запас времени.
Это можно сделать прямо в `function` узле перед сохранением:
// ... внутри блока 'case 'measuring''
const travelTime = endTime - startTime;
const safetyMarginFactor = 1.05; // Запас 5%
const finalTravelTime = Math.round(travelTime * safetyMarginFactor);
node.warn(`Сырое ВПХ: ${travelTime} мс. Итоговое (с запасом 5%): ${finalTravelTime} мс.`);
// Сохраняем итоговое значение
flow.set('full_travel_time_ms', finalTravelTime, 'file');
// ...
Способы хранения калибровочных данных
Выбор способа хранения ВПХ влияет на надежность и гибкость всей системы.
| Способ хранения | Преимущества | Недостатки | Рекомендация |
| ---------------------------- | --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ----------------------------------------------- |
| Переменная `flow.context` | Просто, быстро, изолировано в рамках одной вкладки (flow). | Теряется при перезагрузке, если не настроено персистентное хранилище. | Только для временных данных или быстрой отладки. |
| Контекст в файле (`file`) | Надежно. Значение сохраняется между перезагрузками контроллера HI. Просто в настройке. | Привязано к конкретному экземпляру Node-RED. Сложно для доступа извне. | Основной рекомендуемый способ. |
| MQTT-топик с `retain=true` | Гибко. Значение доступно всей системе, другим контроллерам, системам мониторинга. | Требует работающего MQTT-брокера. Легко случайно перезаписать извне. | Идеально для интеграции и системного мониторинга. |
| База данных MySQL | Максимальная надежность. Возможность хранения истории калибровок, ведение логов. | Сложнее в настройке, требует дополнительных узлов (`node-red-node-mysql`). | Для крупных, сложных объектов с аудитом. |
Для большинства задач на объектах (квартиры, офисы, коттеджи) связка "измерение в Node-RED -> сохранение в контекст `file`" является золотым стандартом, сочетающим надежность и простоту.
Создание сервисного сценария
Жестко "зашивать" логику калибровки в основной поток управления приводом — плохая практика. Гораздо лучше вынести ее в отдельный "сервисный" сценарий.
Такой подход позволяет инженеру по обслуживанию или даже продвинутому пользователю запустить повторную калибровку (например, после замены привода) удаленно, не трогая основной код и не рискуя нарушить его работу.
---
Итоги и следующие шаги
В этом уроке мы сделали критически важный шаг на пути к созданию интеллектуальных систем управления приводами. Мы深入-рассмотрели концепцию калибровки и ее необходимость для устройств без обратной связи по положению.
Ключевые результаты:Теперь в арсенале нашего контроллера есть точное и надежно сохраненное знание о том, сколько времени требуется конкретной шторе, воротам или клапану для полного цикла работы. Это знание — фундамент, на котором мы построим более сложную и удобную для пользователя логику.
🔗 Связанный материал: В следующем уроке, COURSE-05-M06-L05: Управление позицией в процентах, мы будем активно использовать полученное значение ВПХ для реализации команд вида "установить штору на 30%" или "плавно закрыть на 80%". Мы превратим абстрактные миллисекунды в интуитивно понятные проценты.