КОРЗИНА
магазина
8 (499) 500-14-56 | ПН. - ПТ. 12:00-18:00
ЛЕСНОРЯДСКИЙ ПЕРЕУЛОК, 18С2, БЦ "ДМ-ПРЕСС"

Блок перистальтических насосов RS485 / Modbus

Общие сведения:

Блок перистальтическиx насосов RS485 / Modbus - является устройством включающим в себя до трех насосов, управление которыми осуществляется по протоколу Modbus шины RS485. Так же в блок входят разъемы для подключения двух датчиков уровня жидкости XKC-Y25-V для каждого насоса, сигналы с датчиков можно принимать по протоколу Modbus шины RS485.

Устройство можно использовать для перекачивания различных жидкостей в соответствии с их текущим уровнем в резервуарах гидропонной установки. Устройство легко подключается к блоку управления гидропонной установки, сетевым кабелем через разъемы RJ45.

Блок перистальтическиx насосов не обязательно использовать в гидропонных установках, это могут быть иные проекты где требуется перекачивать различные жидкости с высокой точностью дозации под управлением по протоколу Modbus широко применяемому в промышленности.

В соответствии с протоколом Modbus, к одной шине RS485 можно подключить до 247 блоков перистальтическиx насосов. Адрес устройства (по умолчанию 0x02) назначается программно и хранится в его энергонезависимой памяти. Все устройства на шине должны иметь уникальный адрес.

Насосы:

Жидкость в перистальтических насосах перекачивается по трубке и не контактирует с механизмами насоса. Конструкция насосов позволяет перекачивать жидкости с точностью до грамма.

Блоки с насосами Kamoer NKP-DC-S08 имеют производительность до 60 мл/мин. Насосы комплектуются силиконовой трубкой средней химической стойкости с ресурсом до 200 ч. Эти трубки не предназначены для перекачивания кислот и щелочей.

Блоки с насосами Kamoer KPHM100 имеют производительность до 120 мл/мин. Насосы комплектуются трубкой Pharmed BPT высокой химической стойкости с ресурсом до 1000 ч. Эти трубки могут использоваться для перекачивания даже кислот и щелочей.

Трубки насосов являются расходным материалом и легко меняются. Вне зависимости от токо, какой из представленных насосов используется в блоке, его трубку можно заменить на силиконовую с диаметром: 2x4 или 3x5, или Pharmed BPT с диаметром: 2x4 или 3x5.

Видео:

Редактируется...

Спецификация:

  • Напряжение питания: от 12 до 24 В постоянного тока (разъем RJ45).
  • Ток потребляемый модулем: до 600 мА (при работе всех насосов на максимум).
  • Интерфейс: RS485 / Modbus.
  • Скорость шины: 2400 / 4800 / 9600 / 19200 / 38400 / 57600 / 115200 бит/с.
  • Адрес на шине: устанавливается программно (по умолчанию 0x02).
  • Регулировка коэффициента заполнения ШИМ: от 0,4 до 100%.
  • Регулировка частоты ШИМ: от 1 до 10'000 Гц.
  • Включение на время: от 0,1 до 6'553,5 сек (максимум 1 час 49 минут 13,5 секунд).
  • Рабочая температура: от 0 до +60 °С.
  • Габариты: 250 x 80 x 70 мм.
  • Вес: ? г.

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

Важно: Перед подключением устройства к шине RS485 нужно отключить питание.

Так называемое «горячее подключение» может повредить устройство!

У блока перистальтическиx насосов имеются два вида разъемов:

  • Разъемы RJ45 - для подключения блока к контроллеру по шине RS485.
  • Разъемы DS1069-04 (CWF-4) - для подключения датчиков уровня жидкости XKC-Y25-V.

Назначение выводов разъема RJ45:

  • 1: «A» - Линия данных (неинвертирующая).
  • 2: «B» - Линия данных (инвертирующая).
  • 3: «NC» - Не используется.
  • 4: «PWR» - Вывод питания от +12 до +24В.
  • 5: «PWR» - Вывод питания от +12 до +24В.
  • 6: «NC» - Не используется.
  • 7: «GND» - Общий вывод питания.
  • 8: «GND» - Общий вывод питания.
  • HL-1: «BLINK» - Индикатор включения (мигает если подано питание).
  • HL-2: «DATA» - Индикатор получения запроса и обнаружения устройства.

У блока имеется два разъема RJ45 шины RS485. Один (любой) разъем используется для подключения блока к контроллеру, а второй можно использовать для подключения других блоков насосов или иных модулей к той же шине RS485.

Назначение индикаторов разъёма RJ45:

  • HL-1 «BLINK» Индикатор включения:
    • Индикатор коротко мигает раз в две секунды -
      значит устройство работает, но не получило ни 1 запроса с подачи питания.
    • Индикатор медленно мигает раз в секунду -
      значит устройство работает, но последний запрос принят более 10 сек. назад.
    • Индикатор часто мигает пять раз в секунду -
      значит устройство работает и последний запрос принят менее 10 сек. назад.
  • HL-2 «DATA» Индикатор получения запроса и обнаружения устройства:
    • Индикатор включается при получении запросов, что позволяет визуально отследить их поступление.
    • Устройству можно отправить команду на постоянное свечение индикатора, что позволит визуально найти устройство с известным адресом среди одинаковых устройств на шине.

Назначение выводов разъема DS1069-04 (CWF-4):

  • 1: «+5V» - Выход питания датчика +5В.
  • 2: «IN» - Вход с датчика уровня жидкости XKC-Y25-V (внутрисхемно подтянут до +5V).
  • 3: «GND» - Общий вывод питания.
  • 4: «MODE» - Режим работы датчика (внутрисхемно подключён к +5V => работа без инверсии).

У блока имеется по два разъема DS1069-04 (CWF-4) на каждый насос, для подключения датчиков XKC-Y25-V. Разъемы обозначены: MIN, MID. Датчик подключённый к разъему MIN регистрирует минимальный уровень жидкости, а датчик MID - средний уровень жидкости. Так как вход IN внутрисхемно подтянут до +5В, то отключение датчика от разъёма равносильно наличию датчика регистрирующего жидкость.

Питание:

Входное напряжение питания модуля от 12 до 24В постоянного тока подаётся через разъем PJ45. Модуль сохраняет работоспособность при снижении питания до 5В. Не подавайте питание выше 24В.

Подробнее о блоке:

Блок перистальтическиx насосов RS485 / Modbus построен на базе микроконтроллера STM32G030F4 и конвертера SN65HVD3082EDR с цепями защиты шины RS485 и встроенным терминатором, который можно отключать переключателем на плате. В устройстве присутствуют: импульсный DC-DC преобразователь, до трех перистальтическиx насосов, за коммутацию которых отвечают мощные HEXFET транзисторы и по два разъема DS1069-04 (CWF-4) на каждый насос, для подключения датчиков уровня жидкости XKC-Y25-V.

Блок позволяет:

  • Менять свой адрес на шине.
  • Менять тип протокола Modbus (RTU/ASCII).
  • Менять скорость передачи данных.
  • Сохранять одно двухбайтное слово в энергонезависимую память и читать его.
  • Читать напряжение питания поступившее с разъема RJ45.
  • Управлять светодиодом обнаружения устройства на разъеме RJ45.
  • Включать/отключать любой из насосов.
  • Включать любой насос на указанное время.
  • Задавать скорость работы каждого насоса (используется ШИМ).
  • Задавать частоту ШИМ для каждого насоса.
  • Включать/отключать сторожевой таймер насосов (общий для всех насосов).
  • Устанавливать время сторожевого таймера до сброса и получать оставшееся время.
  • Получать состояния цифровых датчиков уровня жидкости (если они подключены).

Для работы с блоком перистальтическиx насосов RS485 / Modbus предлагаем воспользоваться разработанными нами библиотеками iarduino_Modbus и iarduino_MB_Pump. Первая позволяет работать по протоколу Modbus на шине RS485, а вторая предназначена для работы с блоком перистальтическиx насосов.

    Подробнее про установку библиотек читайте в нашей инструкции.

    Примеры:

      Предложенные библиотеки содержат больше примеров, доступных из меню Arduino IDE:
    • Файл / Примеры / iarduino Modbus (протокол) / ModbusClient / HardwareSerial.
    • Файл / Примеры / iarduino Modbus (протокол) / ModbusClient / SoftwareSerial.
    • Файл / Примеры / iarduino Modbus Pump (насосы) / HardwareSerial.
    • Файл / Примеры / iarduino Modbus Pump (насосы) / SoftwareSerial.

    Так как у большинства плат Arduino и ESP нет шины RS485, то библиотека iarduino_Modbus использует аппаратную или программную шину UART, сигналы которой преобразуются в сигналы шины RS485 при помощи конвертирующего модуля UART-RS485, например, на базе микросхемы MAX485. Конвертер подключается к выводам TX и RX шины UART, а так же назначается вывод разрешающий работу передатчика DE.

    Для более удобного подключения, можно воспользоваться Trema конвертером UART-RS485, как показано на картинке ниже. У этого конвертера имеется порт RJ-45, который позволяет подключать датчик при помощи стандартного 8-жильного кабеля витой пары патч-корд.

    Обратите внимание на то, что вывод TX конвертера подключается к выводу RX Arduino, вывод RX конвертера к выводу TX Arduino, вывод разрешения работы передатчика D (DE) подключается к любому выводу Arduino (назначается в скетче).

    В примерах ниже, для создания шины RS485, будет использована аппаратная шина UART1 (класс Serial1). Если у вашей платы Arduino нет свободных аппаратных шин UART, используйте программную шину UART при помощи входящей в состав Arduino IDE библиотеки SoftwareSerial.

    Смена адреса блока на шине:

    Пример меняет текущий адрес блока (nowAddress) на новый (newAddress) и сохраняет его в энергонезависимую память блока, значит адрес сохранится и после отключения питания.

    uint8_t nowAddress = 2;                     // Текущий адрес блока перистальтическиx насосов ( 1 - 247 ).
    uint8_t newAddress = 10;                    // Новый адрес блока перистальтическиx насосов ( 1 - 247 ).
    uint8_t pinDE      = 2;                     // Вывод DE конвертера UART-RS485.
                                                //
    #include <iarduino_Modbus.h>                // Подключаем библиотеку для работы по протоколу Modbus.
    #include <iarduino_MB_Pump.h>               // Подключаем библиотеку для работы с блоком перистальтическиx насосов.
                                                //
    ModbusClient modbus(Serial1, pinDE);        // Создаём объект для работы по протоколу Modbus указав шину UART-RS485 и вывод DE.
    iarduino_MB_Pump pump(modbus);              // Создаём объект для работы с перистальтическими насосами указав объект протокола Modbus.
                                                //
    void setup(){                               //
         int f;                                 //
         Serial.begin(9600); while(!Serial);    // Инициируем передачу данных в монитор последовательного порта, указав его скорость.
         Serial1.begin(9600); while(!Serial1);  // Инициируем работу с шиной UART подключённой к конвертеру UART-RS485.
         modbus.begin();                        // Инициируем работу по протоколу Modbus.
    //   modbus.setTimeout(10);                 // Указываем максимальное время ожидания ответа по протоколу Modbus.
    //   modbus.setDelay(4);                    // Указываем минимальный интервал между отправляемыми сообщениями по протоколу Modbus.
    //   modbus.setTypeMB( MODBUS_RTU );        // Указываем тип протокола Modbus: MODBUS_RTU (по умолчанию), или MODBUS_ASCII.
         Serial.print("Инициализация ");        //
         f =    pump.begin(nowAddress);         // Инициируем работу с блоком перистальтическиx насосов, указав его текущий адрес nowAddress.
         if(f){ Serial.println("OK");  }        // Если f=true значит инициализация пройдена успешно.
         else { Serial.println("ERR"); }        // Если f=false значит инициализация не пройдена.
         Serial.print("Смена адреса ");         //
         f =    pump.changeID(newAddress);      // Меняем адрес блока перистальтическиx насосов на новый newAddress.
         if(f){ Serial.println("OK");  }        // Если f=true значит адрес изменён.
         else { Serial.println("ERR"); }        // Если f=false значит адрес не изменён.
         Serial.print("Текущий адрес ");        //
         Serial.println(pump.getID());          // Выводим текущий адрес блока перистальтическиx насосов.
         Serial.print("Версия прошивки ");      //
         Serial.println(pump.getVersion());     // Выводим версию прошивки блока перистальтическиx насосов.
    }                                           //
                                                //
    void loop(){                                // Визуально показываем у какого устройства был изменён адрес.
         pump.setIDLED(true ); delay(1000);     // Включаем светодиодом обнаружения устройства (на разъёме RJ45).
         pump.setIDLED(false); delay(1000);     // Выключаем светодиодом обнаружения устройства (на разъёме RJ45).
    }                                           //
    

    Пример будет более коротким, если убрать вывод данных в монитор последовательного порта и обращаться к функциям pump.begin(), pump.changeID() без проверки f. Если при обращении к функции pump.begin() не указывать текущий адрес блока nowAddress, то он будет найден автоматически, но это займёт некоторое время.

    Управление насосами:

    Пример включает насос «A» на 1 секунду и насос «B» на 2 секунды, далее ждёт 1 секунду и всё повторяется.

    uint8_t pinDE = 2;                          // Вывод DE конвертера UART-RS485.
    int f;                                      // Переменная для получения ответов от блока перистальтическиx насосов.
                                                //
    #include <iarduino_Modbus.h>                // Подключаем библиотеку для работы по протоколу Modbus.
    #include <iarduino_MB_Pump.h>               // Подключаем библиотеку для работы с блоком перистальтическиx насосов.
                                                //
    ModbusClient modbus(Serial1, pinDE);        // Создаём объект для работы по протоколу Modbus указав шину UART-RS485 и вывод DE.
    iarduino_MB_Pump pump(modbus);              // Создаём объект для работы с перистальтическими насосами указав объект протокола Modbus.
                                                //
    void setup(){                               //
         Serial.begin(9600); while(!Serial);    // Инициируем передачу данных в монитор последовательного порта, указав его скорость.
         Serial1.begin(9600); while(!Serial1);  // Инициируем работу с шиной UART подключённой к конвертеру UART-RS485.
         modbus.begin();                        // Инициируем работу по протоколу Modbus.
    //   modbus.setTimeout(10);                 // Указываем максимальное время ожидания ответа по протоколу Modbus.
    //   modbus.setDelay(4);                    // Указываем минимальный интервал между отправляемыми сообщениями по протоколу Modbus.
    //   modbus.setTypeMB( MODBUS_RTU );        // Указываем тип протокола Modbus: MODBUS_RTU (по умолчанию), или MODBUS_ASCII.
         f = pump.begin(2);                     // Инициируем работу с блоком перистальтических насосов, указав его адрес.
         if( !f ){                              // Если функция begin() вернула false, значит блок перистальтическиx насосов с адресом 2 не найден.
             Serial.print("Блок не найден");    //
             while(1);                          // Запрещаем дальнейшее выполнение скетча.
         }                                      //
    }                                           //
                                                //
    void loop(){                                //
    //   Включаем насосы «A» и «B»:             //
         f = pump.setState(PUMP_ALL,true,true); // Отправляем команду включения насосов «A» и «B». Для насоса «С» добавляется еще 1 параметр.
         if( !f ){ Serial.println("ON=ERR"); }  // Сообщаем о отсутствии связи.
         delay(1000);                           // Ждём 1 секунду.
    //   Отключаем насос «A»:                   //
         f = pump.setState(PUMP_A, false);      // Отправляем команду отключения насоса «A».
         if( !f ){ Serial.println("A=ERR"); }   // Сообщаем о отсутствии связи.
         delay(1000);                           // Ждём 1 секунду.
    //   Отключаем насос «B»:                   //
         f = pump.setState(PUMP_B, false);      // Отправляем команду отключения насоса «B».
         if( !f ){ Serial.println("B=ERR"); }   // Сообщаем о отсутствии связи.
         delay(1000);                           // Ждём 1 секунду.
    }                                           //
    

    Первая команда функции loop() включает насосы «A» и «B» setState(PUMP_ALL,true,true). Если добавить еще один параметр setState(PUMP_ALL,true,true,true), то включится и насос «С» (если он есть). А можно включить каждый насос по отдельности setState(PUMP_A, true) setState(PUMP_B, true). Этот пример кажется большим, но если убрать все проверки, некоторые комментарии и вывод данных в монитор последовательного порта, то код будет более компактным.

    Пример без вывода данных в монитор и без проверок:

    uint8_t pinDE = 2;                          // Вывод DE конвертера UART-RS485.
                                                //
    #include <iarduino_Modbus.h>                // Подключаем библиотеку для работы по протоколу Modbus.
    #include <iarduino_MB_Pump.h>               // Подключаем библиотеку для работы с блоком перистальтическиx насосов.
                                                //
    ModbusClient modbus(Serial1, pinDE);        // Создаём объект для работы по протоколу Modbus указав шину UART-RS485 и вывод DE.
    iarduino_MB_Pump pump(modbus);              // Создаём объект для работы с перистальтическими насосами указав объект протокола Modbus.
                                                //
    void setup(){                               //
         Serial1.begin(9600); while(!Serial1);  // Инициируем работу с шиной UART подключённой к конвертеру UART-RS485.
         modbus.begin();                        // Инициируем работу по протоколу Modbus.
         pump.begin(2);                         // Инициируем работу с блоком перистальтических насосов, указав его адрес.
    }                                           //
                                                //
    void loop(){                                //
         pump.setState(PUMP_ALL, true, true);   // Отправляем команду включения насосов «A» и «B». Для насоса «С» добавляется еще 1 параметр.
         delay(1000);                           // Ждём 1 секунду.
         pump.setState(PUMP_A, false);          // Отправляем команду отключения насоса «A».
         delay(1000);                           // Ждём 1 секунду.
         pump.setState(PUMP_B, false);          // Отправляем команду отключения насоса «B».
         delay(1000);                           // Ждём 1 секунду.
    }                                           //
    

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

    Включение насосов на время:

    Предыдущий пример отправлял модулю три команды через определённые интервалы времени: 1 - включить насосы «A» и «B», 2 - выключить насос «A», 3 - выключить насос «B». Следующий пример отправляет всего одну команду - включить насосы на указанное время.

    Данный пример включает те же насосы на то же время, что и в предыдущем примере:

    uint8_t pinDE = 2;                          // Вывод DE конвертера UART-RS485.
    int f;                                      // Переменная для получения ответов от блока перистальтическиx насосов.
                                                //
    #include <iarduino_Modbus.h>                // Подключаем библиотеку для работы по протоколу Modbus.
    #include <iarduino_MB_Pump.h>               // Подключаем библиотеку для работы с блоком перистальтическиx насосов.
                                                //
    ModbusClient modbus(Serial1, pinDE);        // Создаём объект для работы по протоколу Modbus указав шину UART-RS485 и вывод DE.
    iarduino_MB_Pump pump(modbus);              // Создаём объект для работы с перистальтическими насосами указав объект протокола Modbus.
                                                //
    void setup(){                               //
         Serial.begin(9600); while(!Serial);    // Инициируем передачу данных в монитор последовательного порта, указав его скорость.
         Serial1.begin(9600); while(!Serial1);  // Инициируем работу с шиной UART подключённой к конвертеру UART-RS485.
         modbus.begin();                        // Инициируем работу по протоколу Modbus.
    //   modbus.setTimeout(10);                 // Указываем максимальное время ожидания ответа по протоколу Modbus.
    //   modbus.setDelay(4);                    // Указываем минимальный интервал между отправляемыми сообщениями по протоколу Modbus.
    //   modbus.setTypeMB( MODBUS_RTU );        // Указываем тип протокола Modbus: MODBUS_RTU (по умолчанию), или MODBUS_ASCII.
         pump.begin(2);                         // Инициируем работу с блоком перистальтических насосов, указав его адрес.
    }                                           //
                                                //
    void loop(){                                //
    //   Включаем насосы «A» и «B» на время:    //
         f=pump.setTimeOn(PUMP_ALL, 1.0, 2.0);  // Отправляем команду включения насосов: «A» на 1.0 сек, «B» на 2.0 сек. Для насоса «С» добавляется еще одно время.
         if( !f ){ Serial.println("ON=ERR"); }  // Сообщаем о отсутствии связи.
         delay(3000);                           // Ждём 3 секунды.
    }                                           //
    

    В этом примере за временем работы насосов следит не Arduino, а сам блок насосов.

    Чтение состояний датчиков уровня жидкости:

    Пример опрашивает 4 датчика уровня жидкости (MIN-A, MID-A, MIN-B, MID-B) и выводит их состояние в монитор последовательного порта.

    uint8_t pinDE = 2;                          // Вывод DE конвертера UART-RS485.
    int f;                                      // Переменная для получения ответов от блока перистальтическиx насосов.
                                                //
    #include <iarduino_Modbus.h>                // Подключаем библиотеку для работы по протоколу Modbus.
    #include <iarduino_MB_Pump.h>               // Подключаем библиотеку для работы с блоком перистальтическиx насосов.
                                                //
    ModbusClient modbus(Serial1, pinDE);        // Создаём объект для работы по протоколу Modbus указав шину UART-RS485 и вывод DE.
    iarduino_MB_Pump pump(modbus);              // Создаём объект для работы с перистальтическими насосами указав объект протокола Modbus.
                                                //
    void setup(){                               //
         Serial.begin(9600); while(!Serial);    // Инициируем передачу данных в монитор последовательного порта, указав его скорость.
         Serial1.begin(9600); while(!Serial1);  // Инициируем работу с шиной UART подключённой к конвертеру UART-RS485.
         modbus.begin();                        // Инициируем работу по протоколу Modbus.
    //   modbus.setTimeout(10);                 // Указываем максимальное время ожидания ответа по протоколу Modbus.
    //   modbus.setDelay(4);                    // Указываем минимальный интервал между отправляемыми сообщениями по протоколу Modbus.
    //   modbus.setTypeMB( MODBUS_RTU );        // Указываем тип протокола Modbus: MODBUS_RTU (по умолчанию), или MODBUS_ASCII.
         pump.begin(2);                         // Инициируем работу с блоком перистальтических насосов, указав его адрес.
    }                                           //
                                                //
    void loop(){                                // Визуально показываем у какого устройства был изменён адрес.
    f =  pump.digitalRead(PUMP_SENSOR_MIN_A);   // Запрашиваем состояние датчика MIN насоса «A».
         Serial.print("MIN A = ");              //
         if(f<0 ){ Serial.print("ERR"); }       // Ошибка чтения.
         else    { Serial.print(  f  ); }       // Состояние датчика (0/1).
    f =  pump.digitalRead(PUMP_SENSOR_MID_A);   // Запрашиваем состояние датчика MID насоса «A».
         Serial.print(", MID A = ");            //
         if(f<0 ){ Serial.print("ERR"); }       // Ошибка чтения.
         else    { Serial.print(  f  ); }       // Состояние датчика (0/1).
    f =  pump.digitalRead(PUMP_SENSOR_MIN_B);   // Запрашиваем состояние датчика MIN насоса «B».
         Serial.print(", MIN B = ");            //
         if(f<0 ){ Serial.print("ERR"); }       // Ошибка чтения.
         else    { Serial.print(  f  ); }       // Состояние датчика (0/1).
    f =  pump.digitalRead(PUMP_SENSOR_MID_B);   // Запрашиваем состояние датчика MID насоса «B».
         Serial.print(", MID B = ");            //
         if(f<0 ){ Serial.print("ERR"); }       // Ошибка чтения.
         else    { Serial.print(  f  ); }       // Состояние датчика (0/1).
         Serial.println('.');                   //
         delay(1000);                           //
    }                                           //
    

    Для получения состояний датчиков MIN-C или MID-C необходимо указать в качестве аргумента функции pump.digitalRead() значение PUMP_SENSOR_MIN_C или PUMP_SENSOR_MID_C.

    Если при обращении к функции pump.digitalRead() указать в качестве аргумента значение PUMP_SENSOR_ALL, то функция вернёт байт, шесть младших битов которого отражают состояние всех шести датчиков: (0, 0, MID-C, MIN-C, MID-B, MIN-B, MID-A, MIN-A)2.

    Описание функций библиотеки:

    В данном разделе описаны функции библиотеки iarduino_MB_Pump для работы с:

    Эта библиотека работает совместно с библиотекой iarduino_Modbus, описание функций которой доступно по ссылке Wiki - Работа с протоколом Modbus RTU/ASCI по шине RS485.

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

    В примерах вход DE конвертера UART-RS485 подключён к выводу D2 Arduino. Вместо вывода D2 можно использовать любой выход Arduino, номер выхода указывается при создании объекта для работы по протоколу Modbus.

    • Если используется аппаратная шина UART:
    #include <iarduino_Modbus.h>          // Подключаем библиотеку для работы по протоколу Modbus.
    #include <iarduino_MB_Pump.h>         // Подключаем библиотеку для работы с блоком перистальтическиx насосов.
                                          //
    ModbusClient     modbus(Serial, 2);   // Создаём объект для работы по протоколу Modbus указав класс Serial и номер вывода DE конвертера UART-RS485.
    iarduino_MB_Pump pump(modbus);        // Создаём объект для работы с блоком перистальтическиx насосов, указав объект протокола Modbus.
                                          //
    void setup(){                         //
         ...                              //
         Serial.begin(9600);              // Указываем скорость шины RS485. Она равна скорости шины UART подключённой к конвертеру UART-RS485.
         while(!Serial);                  //
         pump.begin(2);                   // Инициируем работу с блоком перистальтическиx насосов, указав его адрес.
         ...                              //
    }                                     //
    

    Если используется аппаратная шина UART-1, то вместо класса Serial указываем Serial1, для шины UART2 указываем Serial2 и т.д.

    • Если используется программная реализация шины UART:
    #include <SoftwareSerial.h>           // Подключаем библиотеку для работы с программной шиной UART.
    #include <iarduino_Modbus.h>          // Подключаем библиотеку для работы по протоколу Modbus.
    #include <iarduino_MB_Pump.h>         // Подключаем библиотеку для работы с блоком перистальтическиx насосов.
                                          //
    SoftwareSerial   rs485(8, 9);         // Создаём объект для работы с программной шиной UART указывая выводы RX, TX.
    ModbusClient     modbus(rs485, 2);    // Создаём объект для работы по протоколу Modbus указав объект программной шины UART и номер вывода DE конвертера UART-RS485.
    iarduino_MB_Pump pump(modbus);        // Создаём объект для работы с блоком перистальтическиx насосов, указав объект протокола Modbus.
                                          //
    void setup(){                         //
         ...                              //
         rs485.begin(9600);               // Указываем скорость шины RS485. Она равна скорости программной шины UART подключённой к конвертеру UART-RS485.
         while(!rs485);                   //
         pump.begin(2);                   // Инициируем работу с блоком перистальтическиx насосов, указав его адрес.
         ...                              //
    }                                     //
    

    Для программной реализации шины UART необходимо указать выводы которые будут использоваться как RX и TX, в примере указаны выводы 8, и 9 соответственно. При создании объекта modbus указывается не класс Serial, а объект для работы с программной шиной UART.

    Скорость передачи данных по шине Modbus равна скорости шины UART.

    Функция begin();

    • Назначение: Инициализация работы с блоком перистальтическиx насосов.
    • Синтаксис: begin( [ АДРЕС_МОДУЛЯ ] );
    • Параметр: АДРЕС_МОДУЛЯ uint8_t - значение от 1 до 247.
    • Возвращаемое значение: bool - результат инициализации (true или false).
    • Примечание:
      • Если вызвать функцию без параметра, то адрес блока перистальтическиx насосов будет найден автоматически. На это уйдёт некоторое время и на шине долен быть только один блок перистальтическиx насосов.
      • Функцию достаточно вызвать 1 раз в коде Setup(), до обращения к остальным функциям библиотеки.
      • Блоки перистальтическиx насосов поставляются с адресом 2 на шине, но этот адрес можно изменить.
    • Пример:
    pump.begin(2); // Инициируем работу с блоком перистальтическиx насосов, указав его адрес на шине.
    

    Функция reset();

    • Назначение: Программная перезагрузка блока перистальтическиx насосов.
    • Синтаксис: reset();
    • Параметры: Нет.
    • Возвращаемое значение: bool - результат перезагрузки (true или false).
    • Пример:
    pump.reset(); // Выполняем программную перезагрузку.
    

    Функция changeID();

    • Назначение: Установка нового адреса на шине.
    • Синтаксис: changeID( АДРЕС_МОДУЛЯ );
    • Параметр: АДРЕС_МОДУЛЯ uint8_t - значение от 1 до 247.
    • Возвращаемое значение: bool - результат изменения адреса (true или false).
    • Примечание:
      • Новый адрес сохраняется в энергонезависимую память, а значит остаётся после отключения питания.
      • Выполнение функции занимает более 120 миллисекунд.
    • Пример:
    pump.changeID(10); // Изменить адрес модуля на значение 10.
    

    Функция setSpeedMB();

    • Назначение: Установка новой скорости передачи данных.
    • Синтаксис: setSpeedMB( СКОРОСТЬ );
    • Параметр: СКОРОСТЬ uint32_t - может принимать одно из значений:
      2400 / 4800 / 9600 / 19200 / 38400 / 57600 / 115200.
    • Возвращаемое значение: bool - результат изменения скорости (true или false).
    • Примечание:
      • Новая скорость применяется на 2 секунды, в течении которых её нужно подтвердить.
      • Если скорость не подтвердить в течении 2 секунд, модуль вернёт прежнюю скорость.
      • Скорость подтверждается функцией ackSpeedMB() на новой скорости шины.

    Функция ackSpeedMB();

    • Назначение: Подтверждение смены скорости передачи данных.
    • Синтаксис: ackSpeedMB();
    • Параметры: Нет.
    • Возвращаемое значение: bool - результат подтверждения скорости (true или false).
    • Примечание:
      • Подтверждение скорости выполняется после установки новой скорости модуля функцией setSpeedMB() и установки той же скорости для шины UART-RS485.
      • Если скорость не подтвердить в течении 2 секунд, модуль вернёт прежнюю скорость.
      • Подтверждённая скорость сохраняется в энергонезависимую память, а значит остаётся после отключения питания.
      • Выполнение функции занимает более 50 миллисекунд.
    • Пример:
    pump.setSpeedMB(9600); // Изменить скорость модуля на 9600 бит/сек.
    Serial.begin(9600);    // Изменить скорость шины UART-RS485 на 9600 бит/сек.
    pump.ackSpeedMB();     // Подтвердить скорость модуля.
    

    Функция setTypeMB();

    • Назначение: Установка нового типа протокола Modbus.
    • Синтаксис: setTypeMB( ТИП );
    • Параметр: ТИП uint8_t - может принимать значение MODBUS_RTU или MODBUS_ASCII.
    • Возвращаемое значение: bool - результат изменения типа протокола (true или false).
    • Примечание:
      • Новый тип протокола применяется на 2 секунды, в течении которых его нужно подтвердить.
      • Если тип протокола не подтвердить в течении 2 секунд, модуль вернёт прежний тип.
      • Тип протокола подтверждается функцией ackTypeMB() по новому типу протокола на шине.

    Функция ackTypeMB();

    • Назначение: Подтверждение смены типа протокола Modbus.
    • Синтаксис: ackTypeMB();
    • Параметры: Нет.
    • Возвращаемое значение: bool - результат подтверждения типа протокола (true или false).
    • Примечание:
      • Подтверждение типа протокола Modbus выполняется после установки нового типа протокола модуля функцией setTypeMB() и установки того-же типа протокола для передачи данных по шине UART-RS485.
      • Если тип протокола не подтвердить в течении 2 секунд, модуль вернёт прежний тип.
      • Подтверждённый тип протокола Modbus сохраняется в энергонезависимую память, а значит остаётся после отключения питания.
      • Выполнение функции занимает более 50 миллисекунд.
    • Пример:
    pump.setTypeMB(MODBUS_RTU);   // Изменить тип протокола модуля на Modbus RTU.
    modbus.setTypeMB(MODBUS_RTU); // Изменить тип протокола шины UART-RS485 на Modbus RTU.
    pump.ackTypeMB();             // Подтвердить тип протокола модуля.
    

    Функция writeFlash();

    • Назначение: Запись пользовательского значения в Flash память.
    • Синтаксис: writeFlash( ЧИСЛО );
    • Параметр: ЧИСЛО uint16_t - любое значение от 0 до 65535.
    • Возвращаемое значение: bool - результат записи (true или false).
    • Примечание:
      • Записываемое число сохраняется в энергонезависимую память, а значит остаётся после отключения питания.
      • Выполнение функции занимает более 50 миллисекунд.
      • Для чтения числа из Flash памяти воспользуйтесь функцией readFlash().
      • Число хранится в регистре "Holding Registers" [0x0120] «USER_DATA».
    • Пример:
    pump.writeFlash(12345); // Записать число в энергонезависимую память.
    

    Функция readFlash();

    • Назначение: Чтение пользовательского значения из Flash памяти.
    • Синтаксис: readFlash();
    • Параметры: Нет.
    • Возвращаемое значение: int32_t - число из памяти (0...65535) , или -1 при провале чтения.
    • Примечание:
      • Для записи числа в Flash память воспользуйтесь функцией writeFlash().
      • Число хранится в регистре "Holding Registers" [0x0120] «USER_DATA».
    • Пример:
    i = pump.readFlash();           // Читаем число из энергонезависимой памяти.
    if(i<0){ Serial.print("ERR"); } // Сообщаем о ошибке.
    else   { Serial.print(  i  ); } // Выводим прочитанное значение.
    

    Функция getID();

    • Назначение: Чтение адреса устройства на шине.
    • Синтаксис: getID();
    • Параметры: Нет.
    • Возвращаемое значение: uint8_t - адрес (1...247), или 0 если устройство не инициировано.
    • Примечание:
      • Данная функция может пригодиться если инициализация устройства выполнена функцией begin() без указания адреса (адрес найден автоматически).
    • Пример:
    i = pump.getID();                // Читаем адрес устройства на шине.
    if(i==0){ Serial.print("ERR"); } // Сообщаем о ошибке.
    else    { Serial.print(  i  ); } // Выводим адрес устройства на шине.
    

    Функция getVersion();

    • Назначение: Чтение версии прошивки устройства.
    • Синтаксис: getVersion();
    • Параметры: Нет.
    • Возвращаемое значение: uint8_t - версия прошивки, или 0 если устройство не инициировано.
    • Пример:
    i = pump.getVersion();           // Читаем версию прошивки устройства.
    if(i==0){ Serial.print("ERR"); } // Сообщаем о ошибке.
    else    { Serial.print(  i  ); } // Выводим версию прошивки устройства.
    

    Функция getSumPump();

    • Назначение: Чтение количества насосов у блока.
    • Синтаксис: getSumPump();
    • Параметры: Нет.
    • Возвращаемое значение: uint8_t - количество, или 0 если устройство не инициировано.
    • Примечание: Библиотека работает с блоками на 2 или 3 перистальтическиx насоса.
    • Пример:
    i = pump.getSumPump();           // Читаем количество насосов у блока.
    if(i==0){ Serial.print("ERR"); } // Сообщаем о ошибке.
    else    { Serial.print(  i  ); } // Выводим количество насосов.
    

    Функция setIDLED();

    • Назначение: Управление индикатором обнаружения устройства.
    • Синтаксис: setIDLED( СОСТОЯНИЕ );
    • Параметр: СОСТОЯНИЕ bool - флаг включения индикатора (true или false).
    • Возвращаемое значение: bool - результат применения состояния индикатора (true или false).
    • Примечание:
      • Индикатор обнаружения устройства - это светодиод на разъеме RJ-45.
      • Если индикатор включён, то светодиод постоянно светится. Так можно визуально определить устройство, если на шине имеются несколько одинаковых устройств.
      • Если индикатор отключен, то светодиод информирует о получении запросов, адресованных этому устройству.
    • Пример:
    pump.setIDLED(true ); // Включаем индикатор обнаружения устройства.
    pump.setIDLED(false); // Отключаем индикатор обнаружения устройства.
    

    Функция getPWR();

    • Назначение: Чтение напряжения питания.
    • Синтаксис: getPWR();
    • Параметры: Нет.
    • Возвращаемое значение: float - напряжение (5,000...24,000 В), или -1 при провале чтения.
    • Примечание:
      • Данная функция позволяет узнать напряжение питания поступившее на разъем RJ45.
      • Функция позволяет возвращать значение за пределами указанного диапазона, но корректная работа устройства при таком питании не гарантируется.
    • Пример:
    i = pump.getPWR();              // Читаем напряжение поступившее на разъем RJ45.
    if(i<0){ Serial.print("ERR"); } // Сообщаем о ошибке.
    else   { Serial.print(  i  ); } // Выводим напряжение питания в вольтах.
    

    Функция setPower();

    • Назначение: Установка мощности насоса.
    • Синтаксис: setPower( НАСОС, МОЩНОСТЬ );
    • Параметры:
      • uint8_t НАСОС - принимает одно из значений: PUMP_A, PUMP_B, PUMP_C, PUMP_ALL.
      • uint8_t МОЩНОСТЬ - коэффициент заполнения ШИМ от 1 (0,4%) до 255 (100%).
    • Возвращаемое значение: bool - результат применения мощности (true или false).
    • Примечание:
      • Мощность насоса задаётся коэффициентом заполнения ШИМ, от которого зависит и скорость насоса.
      • Изменение мощности насоса не включает и не отключает насос.
      • Каждому насосу можно установить свою мощность.
      • Мощность всех насосов по умолчанию: 255 (100%).
      • Если в качестве первого параметра указать PUMP_ALL, то далее нужно задать значения мощности для каждого насоса.
    • Пример:
    pump.setPower(PUMP_A, 255);            // Устанавливаем мощность насоса «A» на 100%.
    pump.setPower(PUMP_B, 127);            // Устанавливаем мощность насоса «B» на 50%.
    pump.setPower(PUMP_ALL, 64, 127, 255); // Устанавливаем мощность для 3 насосов: «A» 25%, «B» 50%, «C» 100%.
    pump.setPower(PUMP_ALL, 64, 127);      // Устанавливаем мощность для 2 насосов, если нет насоса «C».
    

    Функция getPower();

    • Назначение: Чтение мощности насоса.
    • Синтаксис: getPower( НАСОС );
    • Параметр: НАСОС uint8_t - принимает одно из значений: PUMP_A, PUMP_B, PUMP_C.
    • Возвращаемое значение: int16_t - мощность от 1 до 255, или -1 при провале чтения.
    • Примечание:
      • В качестве мощности насоса возвращается коэффициент заполнения ШИМ от 1 до 255.
      • Функция возвращает установленную для насоса мощность, вне зависимости от того включён он или нет.
    • Пример:
    i = pump.getPower(PUMP_A);      // Читаем установленную мощность насоса «A».
    if(i<0){ Serial.print("ERR"); } // Ошибка чтения.
    else   { Serial.print(  i  ); } // Установленная мощность насоса.
    

    Функция setState();

    • Назначение: Управление насосом.
    • Синтаксис: setState( НАСОС, СОСТОЯНИЕ );
    • Параметры:
      • uint8_t НАСОС - принимает одно из значений: PUMP_A, PUMP_B, PUMP_C, PUMP_ALL
      • bool СОСТОЯНИЕ - флаг включения насоса (true или false).
    • Возвращаемое значение: bool - результат применения нового состояния (true или false).
    • Примечание:
      • Если СОСТОЯНИЕ = true, то насос включается на установленной ранее мощности.
      • Обращение к функции отменяет действие функции setTimeOn() для указанного насоса.
      • Включение насоса может блокироваться сторожевым таймером насосов, если он включён.
      • Если в качестве первого параметра указать PUMP_ALL, то далее нужно задать состояния для каждого насоса.
    • Пример:
    pump.setState(PUMP_A, true);                // Включаем  насос «A».
    pump.setState(PUMP_B, false);               // Отключаем насос «B».
    pump.setState(PUMP_ALL, false, true, true); // Управляем всеми насосами: «A» выкл, «B» вкл, «C» вкл.
    pump.setState(PUMP_ALL, false, true);       // Управляем всеми насосами, если их 2.
    

    Функция getState();

    • Назначение: Чтение состояния насоса.
    • Синтаксис: getState( НАСОС );
    • Параметр: НАСОС uint8_t - одно из значений: PUMP_A, PUMP_B, PUMP_C, PUMP_ALL.
    • Возвращаемое значение: int8_t - состояние: 0-откл, 1-вкл, или -1 при провале чтения.
    • Примечание:
      • Если в качестве параметра указать PUMP_A, PUMP_B, или PUMP_C, то функция вернёт состояние указанного насоса (0-откл, 1-вкл).
      • Если в качестве первого параметра указать PUMP_ALL, то функция вернёт байт, три младших бита которого отражают состояние насосов: (0, 0, 0, 0, 0, C, B, A)2.
    • Пример:
    i = pump.getState(PUMP_A);      // Читаем состояние насоса «A».
    if(i<0){ Serial.print("ERR"); } // Ошибка чтения.
    else   { Serial.print(  i  ); } // Выводим состояние насоса «A».
    
    • Пример:
    i = pump.getState(PUMP_ALL);      // Читаем состояние всех насосов одним запросом.
    if(i<0){                          //
        Serial.print("ERR");          // Ошибка чтения.
    }else{                            //
        Serial.print( bitRead(i,0) ); // Выводим состояние насоса «A».
        Serial.print( bitRead(i,1) ); // Выводим состояние насоса «B».
        Serial.print( bitRead(i,2) ); // Выводим состояние насоса «C».
    }                                 //
    

    Функция setTimeOn();

    • Назначение: Включение насоса на указанное время.
    • Синтаксис: setTimeOn( НАСОС, ВРЕМЯ );
    • Параметры:
      • uint8_t НАСОС - принимает одно из значений: PUMP_A, PUMP_B, PUMP_C, PUMP_ALL
      • float ВРЕМЯ - количество секунд с одним знаком после запятой (от 0.0c, до 6553.5c).
    • Возвращаемое значение: bool - результат включения насоса на время (true или false).
    • Примечание:
      • Функция включает насос на время, насос включается на установленной ранее мощности.
      • Оставшееся время работы насоса можно узнать функцией getTimeOn().
      • По истечении указанного времени, блок отключит насос, без команд по шине.
      • Если обратиться к функции указав ВРЕМЯ равное 0.0с, то насос сразу отключится.
      • Обращение к функции отменяет действие функции setState() для указанного насоса.
      • Включение насоса может блокироваться сторожевым таймером насосов, если он включён.
      • Если в качестве первого параметра указать PUMP_ALL, то далее нужно задать время для каждого насоса.
    • Пример:
    pump.setTimeOn(PUMP_A, 2.1);          // Включаем насос «A» на 2.1 секунды.
    pump.setTimeOn(PUMP_B, 3.2);          // Включаем насос «B» на 2.1 секунды.
    pump.setTimeOn(PUMP_ALL, 1.2, 5, 10); // Включаем насосы: «A» на 1.2 сек, «B» на 5.0 сек, «C» на 10.0 сек.
    pump.setTimeOn(PUMP_ALL, 1.2, 5);     // Включаем насосы «A» и «B», если нет насоса «C».
    

    Функция getTimeOn();

    • Назначение: Чтение оставшегося времени работы насоса.
    • Синтаксис: getTimeOn( НАСОС );
    • Параметр: НАСОС uint8_t - одно из значений: PUMP_A, PUMP_B, PUMP_C.
    • Возвращаемое значение: float - время в секундах (0...6553,5), или -1 при провале чтения.
    • Примечание:
      • Если насос включён функцией setTimeOn(), то функция getTimeOn() возвращает время оставшееся до самостоятельного отключения насоса.
      • Если насос включён функцией setState(), то функция getTimeOn() возвращает 0. Так же 0 возвращается если насос выключен.
    • Пример:
    i = pump.getTimeOn(PUMP_A);     // Читаем состояние насоса «A».
    if(i<0){ Serial.print("ERR"); } // Ошибка чтения.
    else   { Serial.print(  i  ); } // Выводим оставшееся время работы насоса «A».
    

    Функция setPomp12V();

    • Назначение: Управление коррекцией питания для насосов до 12В.
    • Синтаксис: setPomp12V( НАСОС, ФЛАГ );
    • Параметры:
      • uint8_t НАСОС - принимает одно из значений: PUMP_A, PUMP_B, PUMP_C, PUMP_ALL
      • bool ФЛАГ - флаг включения коррекции питания насоса (true или false).
    • Возвращаемое значение: bool - результат изменения коррекции питания (true или false).
    • Примечание:
      • Если ФЛАГ = true, то коррекция питания для насосов до 12В будет включена и изменение входного питания от 12 до 24В не будет влиять на скорость работы насоса. Насос будет работать так, как при подаче 12В ±10% на разъём RJ45.
      • Если ФЛАГ = false, то коррекция питания для насосов до 12В будет отключена.
      • Функция не включает насос, не выключает его и не влияет на работу остальных функций.
      • Если в качестве первого параметра указать PUMP_ALL, то далее нужно задать флаги коррекции питания до 12В для каждого насоса.
    • Пример:
    pump.setPomp12V(PUMP_A, true);                // Включаем  коррекцию питания для насоса «A».
    pump.setPomp12V(PUMP_B, false);               // Отключаем коррекцию питания для насоса «B».
    pump.setPomp12V(PUMP_ALL, false, true, true); // Управляем коррекцией питания всех насосов: «A» выкл, «B» вкл, «C» вкл.
    pump.setPomp12V(PUMP_ALL, false, true);       // Управляем коррекцией питания всех насосов, если их 2.
    

    Функция getPomp12V();

    • Назначение: Чтение наличия коррекции питания насоса до 12В.
    • Синтаксис: getPomp12V( НАСОС );
    • Параметр: НАСОС uint8_t - одно из значений: PUMP_A, PUMP_B, PUMP_C, PUMP_ALL.
    • Возвращаемое значение: int8_t - состояние: 0-откл, 1-вкл, или -1 при провале чтения.
    • Примечание:
      • Если в качестве параметра указать PUMP_A, PUMP_B, или PUMP_C, то функция вернёт флаг наличия коррекции питания указанного насоса (0-откл, 1-вкл).
      • Если в качестве первого параметра указать PUMP_ALL, то функция вернёт байт, три младших бита которого являются флагами: (0, 0, 0, 0, 0, C, B, A)2.
    • Пример:
    i = pump.getPomp12V(PUMP_A);    // Читаем наличие коррекции питания насоса «A».
    if(i<0){ Serial.print("ERR"); } // Ошибка чтения.
    else   { Serial.print(  i  ); } // Выводим флаг наличия коррекции питания насоса «A».
    
    • Пример:
    i = pump.getPomp12V(PUMP_ALL);    // Читаем наличие коррекции питания всех насосов одним запросом.
    if(i<0){                          //
        Serial.print("ERR");          // Ошибка чтения.
    }else{                            //
        Serial.print( bitRead(i,0) ); // Выводим флаг наличия коррекции питания насоса «A».
        Serial.print( bitRead(i,1) ); // Выводим флаг наличия коррекции питания насоса «B».
        Serial.print( bitRead(i,2) ); // Выводим флаг наличия коррекции питания насоса «C».
    }                                 //
    

    Функция setFrequency();

    • Назначение: Установка частоты ШИМ питания насоса.
    • Синтаксис: setFrequency( НАСОС, ЧАСТОТА );
    • Параметры:
      • uint8_t НАСОС - принимает одно из значений: PUMP_A, PUMP_B, PUMP_C, PUMP_ALL
      • uint16_t ЧАСТОТА - значение частоты ШИМ в герцах (от 1 Гц до 10'000 Гц).
    • Возвращаемое значение: bool - результат применения новой частоты (true или false).
    • Примечание:
      • Функция setPower() позволяет установить мощность насоса, для этого на насос подается сигнал ШИМ, частоту которого можно изменить функцией setFrequency().
      • Изменение частоты ШИМ не влияет на коэффициент заполнения ШИМ (мощность насоса), но может повлиять на его работу. Например, снизить шум.
      • Изменение частоты ШИМ не включает и не выключает насос.
      • Функцию достаточно вызвать один раз для каждого насоса в коде setup().
      • Частоту ШИМ можно задавать для каждого насоса по отдельности.
      • Если в качестве первого параметра указать PUMP_ALL, то далее нужно задать частоту для каждого насоса.
      • Узнать установленную частоту ШИМ насоса можно функцией getFrequency().
    • Пример:
    pump.setFrequency(PUMP_A, 1000);               // Указываем частоту ШИМ насоса «A» = 1 кГц.
    pump.setFrequency(PUMP_B, 2000);               // Указываем частоту ШИМ насоса «B» = 2 кГц.
    pump.setFrequency(PUMP_ALL, 1000, 1500, 2000); // Указываем частоту ШИМ насосов: «A» 1 кГц, «B» 1.5 кГц, «C» 2 кГц.
    pump.setFrequency(PUMP_ALL, 1000, 1500);       // Указываем частоту ШИМ если у блока 2 насоса.
    

    Функция getFrequency();

    • Назначение: Чтение установленной частоты ШИМ для насоса.
    • Синтаксис: getFrequency( НАСОС );
    • Параметр: НАСОС uint8_t - одно из значений: PUMP_A, PUMP_B, PUMP_C.
    • Возвращаемое значение: int32_t - частота в герцах (1...10'000), или -1 при провале чтения.
    • Примечание:
      • Функция возвращает установленную частоту ШИМ независимо от того, включён ли насос.
    • Пример:
    i = pump.getFrequency(PUMP_A);  // Читаем установленную частоту ШИМ для насоса «A».
    if(i<0){ Serial.print("ERR"); } // Ошибка чтения.
    else   { Serial.print(  i  ); } // Выводим частоту ШИМ установленную для насоса «A».
    

    Функция digitalRead();

    • Назначение: Чтение состояния датчиков уровня жидкости.
    • Синтаксис: digitalRead( ИМЯ );
    • Параметр: ИМЯ uint8_t - может принимать одно из значений:
      • PUMP_SENSOR_MIN_A - получить состояние датчика MIN насоса A.
      • PUMP_SENSOR_MID_A - получить состояние датчика MID насоса A.
      • PUMP_SENSOR_MIN_B - получить состояние датчика MIN насоса B.
      • PUMP_SENSOR_MID_B - получить состояние датчика MID насоса B.
      • PUMP_SENSOR_MIN_C - получить состояние датчика MIN насоса C.
      • PUMP_SENSOR_MID_C - получить состояние датчика MID насоса C.
      • PUMP_SENSOR_ALL - получить состояние всех датчиков одним запросом.
    • Возвращаемое значение: int8_t - флаг состояния датчика, или -1 при провале чтения.
    • Примечание:
      • Если датчик фиксирует наличие жидкости, функция возвращает true.
      • Если датчик не фиксирует наличие жидкости, функция возвращает false.
      • Если читается состояния всех датчиков, функция возвращает байт, шесть младших битов которого являются флагами состояний трех датчиков.
      • Если датчик не подключён, функция возвращает true, как если бы датчик был подключён и фиксировал наличие жидкости. Это гарантирует что жидкость из резервуара никогда не перельётся.
    • Пример:
    i = pump.digitalRead(PUMP_SENSOR_MIN_A); // Читаем состояние датчика MIN насоса «A».
    if(i==1){ Serial.print("OK" ); }else     // Есть жидкость (или датчик отсутствует).
    if(i==0){ Serial.print("NO" ); }else     // Нет жидкости.
            { Serial.print("ERR"); }         // Ошибка связи с блоком.
    

    Функция enableWDT();

    • Назначение: Разрешение работы сторожевого таймера насосов.
    • Синтаксис: enableWDT( ВРЕМЯ );
    • Параметр: ВРЕМЯ uint16_t - количество миллисекунд (1-65'535) устанавливаемое при сбросе.
    • Возвращаемое значение: bool - результат разрешения работы таймера (true или false).
    • Примечание:
      • Если сторожевой таймер работает, он уменьшает своё время, пока не досчитает до 0.
      • Если сторожевой таймер насосов досчитает до 0, он отключит все насосы.
      • Таймер досчитавший до 0 не отключается, он продолжает работать отключая насосы.
      • Отключить сторожевой таймер насосов можно функцией disableWDT().
      • Сброс сторожевого таймера функцией resetWDT(), приведёт к тому, что время таймера установится в значение заданное ранее функцией enableWDT(). Если таймер был включён, то он продолжит уменьшать, но уже новое время.
      • Включённый сторожевой таймер нужно постоянно сбрасывать, не дав ему возможности досчитать до 0. При этом насосы будут нормально работать. Но если пропадёт соединение по шине RS485 или перестанет работать управляющая плата, то команды сброса таймера перестанут поступать к блоку насосов, таймер досчитает до 0 и отключит все насосы.
    • Пример:
    pump.enableWDT( 5000 ); // Разрешаем работу сторожевого таймера насосов, задав ему время 5 секунд.
    

    Функция disableWDT();

    • Назначение: Отключение сторожевого таймера насосов.
    • Синтаксис: disableWDT();
    • Параметры: Нет.
    • Возвращаемое значение: bool - результат отключения таймера (true или false).
    • Примечание: Отключённый сторожевой таймер не влияет на работу насосов.
    • Пример:
    pump.disableWDT(); // Запрещаем работу сторожевого таймера насосов.
    

    Функция resetWDT();

    • Назначение: Сброс сторожевого таймера насосов.
    • Синтаксис: resetWDT();
    • Параметры: Нет.
    • Возвращаемое значение: bool - результат сброса таймера (true или false).
    • Примечание:
      • Если сторожевой таймер работает, он уменьшает своё время, пока не досчитает до 0.
      • Сброс сторожевого таймера, приведёт к тому, что время таймера установится в значение заданное ранее функцией enableWDT(). Если таймер был включён, то он продолжит уменьшать, но уже новое время.
      • Если сторожевой таймер насосов досчитает до 0, он отключит все насосы.
    • Пример:
    pump.resetWDT(); // Сбрасываем время сторожевого таймера в значение заданное функцией enableWDT().
    

    Функция getStateWDT();

    • Назначение: Чтение состояния сторожевого таймера насосов.
    • Синтаксис: getStateWDT();
    • Параметры: Нет.
    • Возвращаемое значение: int8_t - состояние: 0-откл, 1-вкл, или -1 при провале чтения.
    • Примечание:
      • Функция позволяет узнать включён или выключен сторожевой таймер насосов.
      • Включённый сторожевой таймер досчитавший до 0 не отключается автоматически, его время остается равно 0 и он продолжает отключать насосы (не даёт их включить).
      • Если таймер досчитал до 0, то перед включением любого насоса необходимо отключить или сбросить таймер, а потом включить насос.
    • Пример:
    i = pump.getStateWDT();              // Читаем состояние сторожевого таймера насосов.
    if(i==1){ Serial.print("ON!"); }else // Сторожевой таймер насосов включён.
    if(i==0){ Serial.print("OFF"); }else // Сторожевой таймер насосов отключён.
            { Serial.print("ERR"); }     // Ошибка связи с блоком.
    

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

    Рассмотренные выше функции библиотеки iarduino_MB_Pump возвращают не только результат чтения, но и ошибки при записи или чтении. Причину ошибок можно выяснить функцией lastError() библиотеки iarduino_Modbus.

    Функция lastError();

    • Назначение: Получение кода причины последней ошибки.
    • Синтаксис: lastError(); // Функция библиотеки iarduino_Modbus.
    • Параметры: Нет.
    • Возвращаемое значение: uint8_t - код причины последней ошибки.
      • ERROR_ILLEGAL_FUNCTION - Команда запроса не поддерживается модулем.
      • ERROR_ILLEGAL_ADDRESS - У модуля отсутствует регистр с указанным адресом.
      • ERROR_ILLEGAL_VALUE - Недопустимое значение в поле данных запроса.
      • ERROR_DEVICE_FAILURE - Любая невосстановимая ошибка кроме первых трёх.
      • ERROR_ACKNOWLEDGE - Модуль принял запрос, но на обработку требуется время.
      • ERROR_DEVICE_BUSY - Ведомый занят, запрос проигнорирован.
      • ERROR_MEMORY_PARITY - Ошибка чтения/записи файла.
      • ERROR_GATEWAY_UNAVAILABLE - Шина перегружена данными или не настроена.
      • ERROR_GATEWAY_NO_DEVICE - Ведомого устройства нет или от него нет ответа.
      • ERROR_SYNTAX - Ошибка синтаксиса.
      • ERROR_ADR_IARDUINO - Ошибка назначения или сортировки адресов устройств iarduino.
      • ERROR_ADR_RESPONSE - Несовпадение адреса регистра в ответе.
      • ERROR_VAL_RESPONSE - Несовпадение данных в ответе.
      • ERROR_CRC_RESPONSE - Несовпадение CRC в принятом ответе.
      • ERROR_LEN_REQUEST - Размер отправляемого запроса превышает размер буфера.
      • ERROR_LEN_RESPONSE - Размер полученного ответа превышает размер буфера.
    • Пример:
    bool i=pump.setState(PUMP_B, true);  // Включаем насос «B».
    if(i){                               // Если команда принята без ошибок...
        Serial.println( F("Вкл") );      // Выводим сообщение "Вкл".
    }else{                               // Если команда вызвала ошибку...
        switch( modbus.lastError() ){    // Получаем код последней ошибки.
            case ERROR_ILLEGAL_FUNCTION:    Serial.println( F("Модуль не поддерживает команду или функцию запроса")           ); break;
            case ERROR_ILLEGAL_ADDRESS:     Serial.println( F("Запрос содержит недопустимый адрес регистра")                  ); break;
            case ERROR_ILLEGAL_VALUE:       Serial.println( F("Запрос содержит недопустимое значение в поле данных")          ); break;
            case ERROR_DEVICE_FAILURE:      Serial.println( F("Ошибка запроса не связана с командой, адресом или данными")    ); break;
            case ERROR_ACKNOWLEDGE:         Serial.println( F("Модуль сообщает что занят и обработает запрос позже")          ); break;
            case ERROR_DEVICE_BUSY:         Serial.println( F("Модуль сообщает что занят и не будет обрабатывать запрос")     ); break;
            case ERROR_MEMORY_PARITY:       Serial.println( F("Модуль сообщает что произошла ошибка чтения/записи файла")     ); break;
            case ERROR_GATEWAY_UNAVAILABLE: Serial.println( F("Шлюз неправильно настроен или перегружен запросами")           ); break;
            case ERROR_GATEWAY_NO_DEVICE:   Serial.println( F("Модуль которому адресован запрос не отвечает")                 ); break;
            case ERROR_SYNTAX:              Serial.println( F("Ошибка синтаксиса")                                            ); break;
            case ERROR_ADR_IARDUINO:        Serial.println( F("Ошибка назначения или сортировки адресов устройств iarduino")  ); break;
            case ERROR_ADR_RESPONSE:        Serial.println( F("Ответ от модуля содержит недопустимый адрес регистра")         ); break;
            case ERROR_VAL_RESPONSE:        Serial.println( F("Ответ от модуля содержит недопустимое значение в поле данных") ); break;
            case ERROR_CRC_RESPONSE:        Serial.println( F("Несовпадение CRC в ответе модуля")                             ); break;
            case ERROR_LEN_REQUEST:         Serial.println( F("Размер запроса к модулю превышает буфер обмена или ADU")       ); break;
            case ERROR_LEN_RESPONSE:        Serial.println( F("Размер ответа от модуля превышает буфер обмена")               ); break;
            default:                        Serial.println( F("Неизвестная ошибка")                                           ); break;
        }
    }
      Зная причину ошибки, можно принять меры к её устранению:
    • ERROR_GATEWAY_NO_DEVICE - нет ответа от модуля, означает что устройство отсутствует на шине. Причиной данной ошибки может быть, как физическое отключение устройства, так и плохой контакт, или недостаточное питание.
    • ERROR_SYNTAX - ошибка синтаксиса, означает наличие ошибки в коде, например функция вызвавшая данную ошибку была вызвана с некорректными параметрами, или вызвана до инициализации модуля.

    Ссылки:




    Обсуждение

    Гарантии и возврат Используя сайт Вы соглашаетесь с условями