Дата публикации

Автор статьи: Rinat Khairulin

21

Регулятор давления на Arduino: управление насосом по сигналу датчика XGZP6897D

Реализация регулятора давления на Arduino с датчиком XGZP6897D. Гистерезис, настройка ШИМ, ПИД-регулятор, фильтрация, защита и масштабирование до уровня АСУ ТП.

Когда двухпозиционное управление уже не работает

Типовая схема:

Насос включился → давление выросло → выключился → давление упало → снова включился.

В результате:

  • циклический износ двигателя;
  • скачки давления;
  • гидроудары;
  • шум;
  • нестабильная работа при переменном расходе.

Для простых задач допустимо. Для магистралей, пневмолиний и технологических процессов – нет.

Задача: управлять давлением, а не просто включать насос.

Датчик давления

В проекте используется цифровой датчик давления XGZP6847D с интерфейсом I²C. Это не “сырой” пьезорезистивный элемент, а уже калиброванный модуль с встроенным АЦП и температурной компенсацией. Внутри находится сенсор, аналоговый фронт-энд и цифровая обработка, поэтому на выходе мы получаем не напряжение, а готовые числовые данные.

Питание датчика допускается в диапазоне 2.5…5.5 В. Это позволяет работать как с Arduino 5 В, так и с ESP32 3.3 В без дополнительного преобразования уровней, при условии корректной подтяжки шины. Линии SDA и SCL требуют внешних подтягивающих резисторов порядка 4.7 кОм к напряжению питания – это стандартное требование I²C. Логические уровни формируются именно относительно VDD датчика, поэтому важно, чтобы микроконтроллер работал в совместимом диапазоне.

Передача данных осуществляется через регистры I²C. Давление формируется как 24-разрядное знаковое число, температура – как 16-разрядное. Давление читается из трёх последовательных регистров, температура – из двух. Старший бит используется как знак, что важно для вакуумных или двусторонних диапазонов. Это означает, что мы имеем не просто “24 бита точности”, а 24-битное цифровое представление откалиброванного значения.

После чтения получаем значение Pressure_ADC, которое пересчитывается через коэффициент K, зависящий от диапазона датчика. Формула преобразования учитывает знаковый бит и даёт результат в Паскалях. Уже затем можно переводить его в PSI или бар – но с инженерной точки зрения удобнее работать в СИ.

Важно понимать, что датчик выполняет комбинированное преобразование – сначала измеряется температура, затем давление. Поэтому либо проверяется флаг завершения преобразования, либо выдерживается технологическая задержка. Если этого не сделать, можно получить устаревшие данные.

В итоге XGZP6847D даёт стабильный цифровой сигнал с температурной компенсацией, что избавляет от необходимости использовать внешний АЦП и выполнять аналоговую фильтрацию на аппаратном уровне. Это упрощает схему, но переносит ответственность за корректную обработку данных в программную часть.

Силовая часть

Насос постоянного тока нельзя подключать напрямую к пину Arduino. Необходимо:

  • MOSFET с достаточным током;
  • драйвер затвора (желательно);
  • защитный диод параллельно двигателю;
  • общая правильная земля.

Почему “правильная земля”?

Вот здесь чаще всего и ломается проект. Когда силовой ток двигателя идёт через ту же землю, что и логика Arduino, появляются:

  • импульсные просадки;
  • помехи;
  • сбросы МК;
  • ложные показания датчика.

Если ток насоса 5 А, а сопротивление дорожки всего 0,05 Ом то в итоге 5×0,05 = 0,25 В падения. Для логики это уже серьёзно.

Правильная организация земли означает:

  • раздельная силовая и сигнальная земля;
  • соединение в одной точке (звезда);
  • короткие силовые контуры;
  • отсутствие прохождения тока двигателя через землю датчика.

Иначе начинается “лечение кода”, хотя проблема физическая.

Базовый алгоритм – гистерезис

Начинаем с простого.

Подключение библиотек:

#include <Wire.h> #include <XGZP6897D.h> #define K 16 XGZP6897D pressureSensor(K);

Основные параметры:

const int pumpPin = 10; float pressureOffset = 0.07; // коррекция нуля const float maxPressure = 15.0; const float criticalPressure = 10.0; const float hysteresis = 0.5; float dutyCycle = 0; const float increment = 10.0; const float decrement = 2.0;

Логика управления:

void updatePump() { if (pressureSensor.readSensor(temperature, pressure)) { float pressurePsi = (pressure * 0.000145038) - pressureOffset; if (pressurePsi < criticalPressure) { dutyCycle += increment * 2; } else if (pressurePsi < maxPressure - hysteresis) { dutyCycle += increment; } else if (pressurePsi > maxPressure + hysteresis) { dutyCycle -= decrement; } dutyCycle = constrain(dutyCycle, 0, 255); analogWrite(pumpPin, dutyCycle); } }

Это уже намного лучше двухпозиционного управления. Насос не работает в режиме «вкл–выкл», а изменяет производительность, и давление перестаёт прыгать скачками. Но вместе с плавностью появляется новая проблема – система начинает колебаться вокруг уставки.

Причина в том, что регулятор управляет не абстрактным числом, а реальным физическим объектом. У нас есть инерция двигателя, время раскрутки крыльчатки, объём жидкости в системе и сопротивление трубопровода. Когда давление немного ниже уставки, мы увеличиваем ШИМ. Насос не реагирует мгновенно – сначала растёт ток, затем обороты, затем поток, и только потом повышается давление. К моменту, когда датчик фиксирует достижение уставки, система уже «разогнана», и давление по инерции продолжает расти. Регулятор начинает снижать ШИМ, но запаздывание остаётся. В результате возникает перерегулирование.

Дальше процесс повторяется в обратную сторону: давление падает чуть ниже заданного – мощность снова увеличивается. Получается циклический процесс с амплитудой, зависящей от объёма системы, характеристик насоса и шага изменения ШИМ.

Если добавить переменный расход – например, открытие клапана – ситуация усложняется. Давление падает резко, регулятор увеличивает мощность, клапан закрывается, а насос уже работает на повышенной производительности. Возникает скачок.

Отдельное влияние в колебания вносит сам датчик. Даже при цифровом выходе показания содержат шум. Если алгоритм реагирует на каждое изменение, он начинает «дергаться» из-за флуктуаций измерения, а не из-за реального изменения давления.

В итоге гистерезисная схема с шаговым изменением ШИМ превращается в простую дискретную систему управления с запаздыванием. Она работает, но не учитывает динамику объекта. И именно здесь становится понятно, зачем нужен либо фильтр сигнала, либо ПИД-регулятор, который способен учитывать не только текущее отклонение, но и скорость его изменения.

Настройка частоты ШИМ

На Arduino Uno по умолчанию ШИМ 490–980 Гц. Для снижения шума двигателя повышаем до 31.25 кГц.

void setPWMFrequency() { TCCR1B = TCCR1B & 0b11111000 | 0x01; }

Важно: работает только для пинов 9 и 10 (таймер 1).

Почему начинается «дыхание» системы

После перехода на плавное управление ШИМ кажется, что проблема решена. Насос больше не щёлкает как реле, давление не падает ступенчато. Но через некоторое время становится заметно, что система начинает «дышать» – давление медленно колеблется вокруг заданного значения.

Причина в том, что мы управляем не мгновенной величиной, а реальным физическим объектом с запаздыванием. Насос не меняет поток мгновенно. Сначала изменяется ток двигателя, затем обороты, затем создаётся дополнительный напор, и только после этого в линии растёт давление. Между подачей управляющего сигнала и реальным изменением давления проходит время. Регулятор же реагирует на текущее измерение, не зная, что система уже «разогналась».

Добавим к этому объём жидкости в трубопроводе. Жидкость сжимаема незначительно, но сам трубопровод, мембраны, фитинги обладают упругостью. При увеличении производительности насоса энергия сначала накапливается в системе, и давление может продолжать расти даже после того, как мощность уже снижена. Это создаёт перерегулирование – давление выходит выше уставки, затем падает ниже, и цикл повторяется.

Если расход нестабилен, например периодически открывается клапан или меняется нагрузка, картина усложняется. Давление резко падает, регулятор увеличивает мощность, но к моменту компенсации расход уже может измениться обратно. Насос оказывается в режиме постоянной подстройки.

Свою роль играет и измерение. Даже цифровой датчик выдаёт значения с небольшими флуктуациями. Если алгоритм реагирует на каждое минимальное отклонение, он начинает корректировать мощность не из-за реального изменения давления, а из-за шумов измерения. В результате ШИМ «плавает», двигатель постоянно меняет режим, и давление начинает колебаться с небольшой амплитудой.

Это и воспринимается как «дыхание» системы – медленные, повторяющиеся отклонения вокруг уставки. Формально система работает, но она не устойчива в динамическом смысле. Чтобы уменьшить эти колебания, необходимо либо сгладить входной сигнал фильтрацией, либо изменить сам закон регулирования, чтобы он учитывал скорость изменения давления, а не только его текущее значение.

Фильтрация сигнала

Простейший вариант – это скользящее среднее:

const int numReadings = 10; float readings[numReadings]; int readIndex = 0; float total = 0; float filter(float value) { total -= readings[readIndex]; readings[readIndex] = value; total += readings[readIndex]; readIndex = (readIndex + 1) % numReadings; return total / numReadings; }

Теперь регулятор работает с отфильтрованным давлением.

Переход к ПИД

Гистерезис – это приближение. ПИД – это управление динамикой.

#include <PID_v1.h> double setpoint = 15.0; double input, output; double Kp = 2, Ki = 5, Kd = 1; PID myPID(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);

В цикле:

input = filteredPressure; myPID.Compute(); analogWrite(pumpPin, output);

Переход на ПИД-регулятор меняет сам подход к управлению. Если гистерезисная логика реагирует только на факт отклонения – выше или ниже уставки, то ПИД анализирует, насколько сильно система отклонилась, как долго она находится в этом состоянии и с какой скоростью меняется параметр.

Пропорциональная составляющая отвечает за текущее отклонение. Чем больше разница между давлением и уставкой, тем активнее регулятор увеличивает или уменьшает мощность насоса. Это позволяет быстро реагировать на просадки или скачки.

Интегральная часть учитывает накопленную ошибку. Если давление долгое время немного ниже заданного значения, даже при малом отклонении интегратор постепенно увеличит управляющее воздействие, компенсируя статическую ошибку. Именно благодаря этой составляющей система способна «дотянуться» до точного значения, а не оставаться вблизи него.

Дифференциальная часть реагирует на скорость изменения давления. Если давление начинает быстро расти, ПИД заранее снижает мощность, не дожидаясь превышения уставки. Это позволяет уменьшить перерегулирование и сделать поведение системы более спокойным.

В результате давление выходит на заданный уровень быстрее и с меньшими колебаниями. При переменной нагрузке, например при резком открытии клапана, регулятор реагирует не только на сам факт падения давления, но и на динамику изменения, что делает систему более устойчивой.

Однако ПИД не является «магическим» решением. Его коэффициенты зависят от механики конкретной системы, характеристик насоса, объёма линии, сжимаемости среды и даже длины трубопровода. Слишком агрессивные настройки вызывают автоколебания, перегрев двигателя и нестабильность. Слишком осторожные делают систему вялой и медленно реагирующей на изменения.

Поэтому настройка ПИД – это не программная операция, а часть инженерной работы, связанной с пониманием динамики объекта управления. Именно здесь тестовый проект начинает превращаться в реальную систему.

Обработка ошибок

Если датчик перестал отвечать, регулятор продолжит работать с последним корректным значением давления. Для алгоритма всё выглядит нормально, но в реальности система больше не получает достоверных данных. Насос может продолжать наращивать давление или работать в режиме, который уже не соответствует состоянию линии.

Поэтому при нескольких подряд неудачных попытках чтения датчика управление должно переходить в безопасное состояние, в данном случае насос отключается.

int errorCount = 0; const int maxErrors = 5; if (pressureSensor.readSensor(temperature, pressure)) { errorCount = 0; } else { errorCount++; if (errorCount >= maxErrors) { analogWrite(pumpPin, 0); } }

Такой механизм защищает систему от зависания шины I²C, обрыва датчика или сбоя питания сенсора. Вместо неконтролируемого режима устройство переходит в предсказуемое состояние.

Именно это отличает демонстрационный стенд от реального узла управления. В лаборатории можно позволить себе предположить, что «датчик всегда работает». В эксплуатации такое предположение рано или поздно приведёт к аварии.

Полный пример базового скетча (гистерезис + фильтр)

Ниже приведён минимально достаточный вариант регулятора давления с неблокирующим циклом, фильтрацией измерений и защитой при потере связи с датчиком. Управление реализовано по гистерезисному принципу с шаговым изменением ШИМ. Частота дискретизации фиксирована и не блокирует выполнение программы, что позволяет в дальнейшем добавить протоколы связи или логирование без изменения структуры управления.

Этот код предназначен для тестового стенда или учебного проекта. Он демонстрирует корректную организацию цикла регулирования, обработку ошибок и базовую фильтрацию сигнала, но не является промышленным решением. Для эксплуатации в реальной системе потребуется более точная настройка алгоритма.

#include <Wire.h> #include <XGZP6897D.h> #define K 16 XGZP6897D pressureSensor(K); const int pumpPin = 10; // --- Параметры давления --- float pressure = 0.0; float temperature = 0.0; float pressureOffset = 0.07; const float maxPressure = 15.0; // уставка const float criticalPressure = 10.0; // аварийный порог const float hysteresis = 0.5; // --- Управление ШИМ --- float dutyCycle = 0; const float increment = 10.0; const float decrement = 2.0; // --- Фильтр --- const int numReadings = 10; float readings[numReadings]; int readIndex = 0; float total = 0; // --- Контроль ошибок --- int errorCount = 0; const int maxErrors = 5; // --- Тайминг --- unsigned long lastUpdate = 0; const unsigned long controlInterval = 50; // 50 мс // ----------------------------- float filter(float value) { total -= readings[readIndex]; readings[readIndex] = value; total += readings[readIndex]; readIndex = (readIndex + 1) % numReadings; return total / numReadings; } void setPWMFrequency() { // Для Arduino Uno, пины 9 и 10 (Timer1) TCCR1B = TCCR1B & 0b11111000 | 0x01; // предделитель 1 → ~31.25 кГц } void updateControl() { if (pressureSensor.readSensor(temperature, pressure)) { errorCount = 0; float pressurePsi = (pressure * 0.000145038) - pressureOffset; float filtered = filter(pressurePsi); if (filtered < criticalPressure) { dutyCycle += increment * 2; } else if (filtered < maxPressure - hysteresis) { dutyCycle += increment; } else if (filtered > maxPressure + hysteresis) { dutyCycle -= decrement; } dutyCycle = constrain(dutyCycle, 0, 255); analogWrite(pumpPin, dutyCycle); } else { errorCount++; if (errorCount >= maxErrors) { dutyCycle = 0; analogWrite(pumpPin, 0); // fail-safe отключение } } } void setup() { Wire.begin(); pressureSensor.begin(); pinMode(pumpPin, OUTPUT); setPWMFrequency(); // Инициализация фильтра for (int i = 0; i < numReadings; i++) { readings[i] = 0; } } void loop() { unsigned long now = millis(); if (now - lastUpdate >= controlInterval) { lastUpdate = now; updateControl(); } // здесь можно добавлять: // - Modbus // - Serial // - логирование // - HMI }

Когда это становится системой

Пока регулятор управляет одним насосом и работает автономно, это локальное устройство. Оно измеряет давление и меняет мощность и на этом всё заканчивается. Но как только появляется необходимость наблюдать процесс извне, менять уставку без перепрошивки и фиксировать аварийные события, проект перестаёт быть просто алгоритмом управления.

Переход на ESP32 добавляет вычислительный ресурс и сетевые интерфейсы. Это позволяет передавать параметры давления, текущую мощность и состояние насоса по сети. Подключение Modbus TCP или другого промышленного протокола делает устройство видимым для SCADA или ПЛК. Регулятор становится частью общей системы автоматизации.

Добавление HMI-панели меняет способ взаимодействия с оборудованием. Уставка, режим работы и аварийные состояния больше не зашиты в коде, ими управляет оператор. Логирование давления и времени работы позволяет анализировать поведение системы, выявлять нестабильность и оценивать ресурс оборудования. Учёт моточасов и фиксация аварий переводят устройство из режима «работает сейчас» в режим «контролируется во времени».

Именно в этот момент регулятор перестаёт быть экспериментальной схемой на столе. Он начинает выполнять роль элемента инфраструктуры – с наблюдаемостью, управляемостью и предсказуемым поведением в аварийных ситуациях.

Интеграция и развитие проекта

Когда регулятор выходит за рамки лабораторного стенда, неизбежно встаёт вопрос силовой части и надёжности оборудования. Поведение алгоритма напрямую зависит от характеристик реального агрегата, и при работе с промышленными моделями из раздела насосное оборудование необходимо учитывать пусковые токи, напорные характеристики и тепловой режим двигателя. Управление такими нагрузками требует корректно подобранного силового ключа и драйвера, принципы выбора которых подробно разобраны в статье «Силовые ключи и драйверы: безопасное управление моторами и высоковольтными нагрузками».

При переходе к распределённой архитектуре устройство должно взаимодействовать с внешними системами. Передача данных о давлении и состоянии насоса по промышленному протоколу позволяет включить регулятор в общую структуру автоматизации. Практические аспекты такой интеграции описаны в материале «Modbus RTU и TCP/IP на практике», где рассматривается обмен данными между микроконтроллером и верхним уровнем управления.

Если требуется локальное управление и визуализация параметров, используется панель оператора. В этом случае регулятор перестаёт быть закрытым устройством и становится частью человеко-машинного интерфейса. Архитектурные принципы построения таких решений раскрыты в статье о роли HMI в современных системах автоматизации.

Таким образом, простой алгоритм регулирования давления может стать отправной точкой для построения полноценного узла управления, интегрированного в инженерную инфраструктуру. Развитие проекта – это не усложнение кода, а постепенное добавление надёжности, наблюдаемости и управляемости.

Регулятор давления на Arduino: управление насосом по сигналу датчика XGZP6897D

Чтобы оставить комментарий, авторизируйтесь

Комментарии (0)