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

Блок розетка RS485 / Modbus

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

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

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

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

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

Видео:

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

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

  • Напряжение питания: от 12 до 24 В постоянного тока (разъем RJ45).
  • Ток потребляемый модулем: до 60 мА (при включённом реле).
  • Интерфейс: RS485 / Modbus.
  • Скорость шины: 4800 / 9600 / 19200 / 38400 / 57600 / 115200 бит/с.
  • Адрес на шине: устанавливается программно (по умолчанию 0x01).
  • Сетевое напряжение питания: до 250 В переменного тока.
  • Ток потребляемый нагрузкой: до 6 А.
  • Рабочая температура: от 0 до +60 °С.
  • Габариты: 130 x 80 x 86 мм.
  • Вес: ? г.

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

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

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

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

  • Евровилка - для подачи питания нагрузки до 250VAC.
  • Розетка - для подключения нагрузки до 250VAC 6A.
  • Разъемы 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, MAX. Датчик подключённый к разъему MIN регистрирует минимальный уровень жидкости, датчик MID - средний уровень жидкости и датчик MAX - максимальный уровень жидкости. Так как вход IN внутрисхемно подтянут до +5В, то отключение датчика от разъёма равносильно наличию датчика регистрирующего жидкость.

Питание:

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

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

Блок розетки RS485 / Modbus построен на базе микроконтроллера STM32G030F4 и конвертера SN65HVD3082EDR с цепями защиты шины RS485 и встроенным терминатором, который можно отключать переключателем на плате. В устройстве присутствуют: импульсный DC-DC преобразователь, электромеханическое реле и цепи искрогашения, что позволяет работать с индуктивными нагрузками. Сетевое напряжение питания до 250VAC подается на евровилку, а снимается с розетки вмонтированной в корпус устройства.

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

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

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

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

    Примеры:

      Предложенные библиотеки содержат больше примеров, доступных из меню Arduino IDE:
    • Файл / Примеры / iarduino Modbus (протокол) / ModbusClient / HardwareSerial.
    • Файл / Примеры / iarduino Modbus (протокол) / ModbusClient / SoftwareSerial.
    • Файл / Примеры / iarduino Modbus Socket (розетка) / HardwareSerial.
    • Файл / Примеры / iarduino Modbus Socket (розетка) / 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 = 1;                     // Текущий адрес блока розетки ( 1 - 247 ).
    uint8_t newAddress = 10;                    // Новый адрес блока розетки ( 1 - 247 ).
    uint8_t pinDE      = 2;                     // Вывод DE конвертера UART-RS485.
                                                //
    #include <iarduino_Modbus.h>                // Подключаем библиотеку для работы по протоколу Modbus.
    #include <iarduino_MB_Socket.h>             // Подключаем библиотеку для работы с блоком розетки.
                                                //
    ModbusClient modbus(Serial1, pinDE);        // Создаём объект для работы по протоколу Modbus указав шину UART-RS485 и вывод DE.
    iarduino_MB_Socket socket(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 =    socket.begin(nowAddress);       // Инициируем работу с блоком розетки, указав его текущий адрес nowAddress.
         if(f){ Serial.println("OK");  }        // Если f=true значит инициализация пройдена успешно.
         else { Serial.println("ERR"); }        // Если f=false значит инициализация не пройдена.
         Serial.print("Смена адреса ");         //
         f =    socket.changeID(newAddress);    // Меняем адрес блока розетки на новый newAddress.
         if(f){ Serial.println("OK");  }        // Если f=true значит адрес изменён.
         else { Serial.println("ERR"); }        // Если f=false значит адрес не изменён.
         Serial.print("Текущий адрес ");        //
         Serial.println(socket.getID());        // Выводим текущий адрес блока розетки.
         Serial.print("Версия прошивки ");      //
         Serial.println(socket.getVersion());   // Выводим версию прошивки блока розетки.
    }                                           //
                                                //
    void loop(){                                // Визуально показываем у какого устройства был изменён адрес.
         socket.setIDLED(true ); delay(1000);   // Включаем светодиодом обнаружения устройства (на разъёме RJ45).
         socket.setIDLED(false); delay(1000);   // Выключаем светодиодом обнаружения устройства (на разъёме RJ45).
    }                                           //
    

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

    Управление розеткой:

    Пример включает розетку на 10 секунд и выключает её на 2 секунды.

    uint8_t pinDE = 2;                          // Вывод DE конвертера UART-RS485.
    int f;                                      // Переменная для получения ответов от блока розетки.
                                                //
    #include <iarduino_Modbus.h>                // Подключаем библиотеку для работы по протоколу Modbus.
    #include <iarduino_MB_Socket.h>             // Подключаем библиотеку для работы с блоком розетки.
                                                //
    ModbusClient modbus(Serial1, pinDE);        // Создаём объект для работы по протоколу Modbus указав шину UART-RS485 и вывод DE.
    iarduino_MB_Socket socket(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 = socket.begin(1);                   // Инициируем работу с розеткой, указав её адрес.
         if( !f ){                              // Если функция begin() вернула false, значит блок розетки с адресом 1 не найден.
             Serial.print("Розетка не найдена");//
             while(1);                          // Запрещаем дальнейшее выполнение скетча.
         }                                      //
    }                                           //
                                                //
    void loop(){                                //
    //   Включаем розетку:                      //
         f = socket.setState(true);             // Отправляем команду включения розетки.
         if( !f ){ Serial.println("NC"); }      // Сообщаем о отсутствии связи.
    //   Проверяем состояние розетки:           //
         f = socket.getState();                 // Получаем состояние розетки.
         if( f==1 ){ Serial.println("ON"  ); }  // Включена.
         if( f==0 ){ Serial.println("OFF" ); }  // Отключена.
                   { Serial.println("ERR" ); }  // Неизвестно.
         delay(10000);                          // Ждём 10 секунд.
    //   Отключаем розетку:                     //
         f = socket.setState(false);            // Отправляем команду отключения розетки.
         if( !f ){ Serial.println("NC"); }      // Сообщаем о отсутствии связи.
    //   Проверяем состояние розетки:           //
         f = socket.getState();                 // Получаем состояние розетки.
         if( f==1 ){ Serial.println("ON"  ); }  // Включена.
         if( f==0 ){ Serial.println("OFF" ); }  // Отключена.
                   { Serial.println("ERR" ); }  // Неизвестно.
         delay(2000);                           // Ждём 2 секунды.
    }                                           //
    

    Этот пример кажется большим, но если убрать все проверки, некоторые комментарии и вывод данных в монитор последовательного порта, то код будет более компактным.

    Пример включает розетку на 10 секунд и выключает её на 2 секунды без проверок.

    uint8_t pinDE = 2;                          // Вывод DE конвертера UART-RS485.
                                                //
    #include <iarduino_Modbus.h>                // Подключаем библиотеку для работы по протоколу Modbus.
    #include <iarduino_MB_Socket.h>             // Подключаем библиотеку для работы с блоком розетки.
                                                //
    ModbusClient modbus(Serial1, pinDE);        // Создаём объект для работы по протоколу Modbus указав шину UART-RS485 и вывод DE.
    iarduino_MB_Socket socket(modbus);          // Создаём объект для работы с розеткой указав объект протокола Modbus.
                                                //
    void setup(){                               //
         Serial1.begin(9600); while(!Serial1);  // Инициируем работу с шиной UART подключённой к конвертеру UART-RS485.
         modbus.begin();                        // Инициируем работу по протоколу Modbus.
         socket.begin(1);                       // Инициируем работу с розеткой, указав её адрес.
    }                                           //
                                                //
    void loop(){                                //
         socket.setState(true);                 // Отправляем команду включения розетки.
         delay(10000);                          // Ждём 10 секунд.
         socket.setState(false);                // Отправляем команду отключения розетки.
         delay(2000);                           // Ждём 2 секунды.
    }                                           //
    

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

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

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

    uint8_t pinDE = 2;                          // Вывод DE конвертера UART-RS485.
                                                //
    #include <iarduino_Modbus.h>                // Подключаем библиотеку для работы по протоколу Modbus.
    #include <iarduino_MB_Socket.h>             // Подключаем библиотеку для работы с блоком розетки.
                                                //
    ModbusClient modbus(Serial1, pinDE);        // Создаём объект для работы по протоколу Modbus указав шину UART-RS485 и вывод DE.
    iarduino_MB_Socket socket(modbus);          // Создаём объект для работы с розеткой указав объект протокола Modbus.
                                                //
    void setup(){                               //
         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.
         socket.begin(1);                       // Инициируем работу с розеткой, указав её адрес.
    }                                           //
                                                //
    void loop(){                                //
         int i,j;                               // i - наличие (0-нет/1-есть), j - состояние (0-нет жидкости/1-есть жидкость).
         Serial.print("MIN = ");                //
    i =  socket.connectRead(SOCKET_SENSOR_MIN); // Запрашиваем наличие   датчика MIN.
    j =  socket.digitalRead(SOCKET_SENSOR_MIN); // Запрашиваем состояние датчика MIN.
         if(i<0||j<0){ Serial.print("ERR"); }   // Ошибка чтения.
         if(i==0    ){ Serial.print("OUT"); }   // Отсутствие датчика.
         if(i==1    ){ Serial.print(j);     }   // Состояние датчика.
         Serial.print(", MID = ");              //
    i =  socket.connectRead(SOCKET_SENSOR_MID); // Запрашиваем наличие   датчика MID.
    j =  socket.digitalRead(SOCKET_SENSOR_MID); // Запрашиваем состояние датчика MID.
         if(i<0||j<0){ Serial.print("ERR"); }   // Ошибка чтения.
         if(i==0    ){ Serial.print("OUT"); }   // Отсутствие датчика.
         if(i==1    ){ Serial.print(j);     }   // Состояние датчика.
         Serial.print(", MAX = ");              //
    i =  socket.connectRead(SOCKET_SENSOR_MAX); // Запрашиваем наличие   датчика MAX.
    j =  socket.digitalRead(SOCKET_SENSOR_MAX); // Запрашиваем состояние датчика MAX.
         if(i<0||j<0){ Serial.print("ERR"); }   // Ошибка чтения.
         if(i==0    ){ Serial.print("OUT"); }   // Отсутствие датчика.
         if(i==1    ){ Serial.print(j);     }   // Состояние датчика.
         Serial.println('.');                   //
         delay(1000);                           //
    }                                           //
    

    Если при обращении к функциям socket.connectRead() и socket.digitalRead() указать в качестве аргумента значение SOCKET_SENSOR_ALL, то функции вернут байт, три младших бита которого отражают состояние или наличие трех датчиков.

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

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

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

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

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

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

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

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

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

    Функция begin();

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

    Функция reset();

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

    Функция changeID();

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

    Функция setSpeedMB();

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

    Функция ackSpeedMB();

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

    Функция writeFlash();

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

    Функция readFlash();

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

    Функция getID();

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

    Функция getVersion();

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

    Функция setIDLED();

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

    Функция getPWR();

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

    Функция setState();

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

    Функция getState();

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

    Функция digitalRead();

    • Назначение: Чтение состояния датчиков уровня жидкости.
    • Синтаксис: digitalRead( ИМЯ );
    • Параметр: ИМЯ uint8_t - может принимать одно из значений:
      • SOCKET_SENSOR_MIN - получить состояние датчика подключённого к разъему MIN.
      • SOCKET_SENSOR_MID - получить состояние датчика подключённого к разъему MID.
      • SOCKET_SENSOR_MAX - получить состояние датчика подключённого к разъему MAX.
      • SOCKET_SENSOR_ALL - получить состояние всех датчиков одним запросом.
    • Возвращаемое значение: int8_t - флаг состояния датчика, или -1 при провале чтения.
    • Примечание:
      • Если датчик фиксирует наличие жидкости, функция возвращает true.
      • Если датчик не фиксирует наличие жидкости, функция возвращает false.
      • Если читается состояния всех датчиков, функция возвращает байт, три младших бита которого являются флагами состояний трех датчиков.
      • Если датчик не подключён, функция возвращает true, как если бы датчик был подключён и фиксировал наличие жидкости. Это гарантирует что жидкость из резервуара никогда не перельётся.
      • Наличие датчика (подключение) можно проверить функцией connectRead().
    • Пример:
    i = socket.digitalRead(SOCKET_SENSOR_MIN); // Читаем состояние датчика MIN.
    if(i==1){ Serial.print("OK" ); }else       // Есть жидкость (или датчик отсутствует).
    if(i==0){ Serial.print("NO" ); }else       // Нет жидкости.
            { Serial.print("ERR"); }           // Ошибка связи с блоком.
    

    Функция connectRead();

    • Назначение: Чтение наличия подключённого датчика уровня жидкости.
    • Синтаксис: connectRead( ИМЯ );
    • Параметр: ИМЯ uint8_t - может принимать одно из значений:
      • SOCKET_SENSOR_MIN - проверить подключение датчика к разъему MIN.
      • SOCKET_SENSOR_MID - проверить подключение датчика к разъему MID.
      • SOCKET_SENSOR_MAX - проверить подключение датчика к разъему MAX.
      • SOCKET_SENSOR_ALL - проверить подключение всех датчиков одним запросом.
    • Возвращаемое значение: int8_t - флаг подключения датчика, или -1 при провале чтения.
    • Примечание:
      • Если датчик подключён, функция возвращает true.
      • Если датчик не подключён, функция возвращает false.
      • Если проверяется подключение всех датчиков, функция возвращает байт, три младших бита которого являются флагами подключения трех датчиков.
    • Пример:
    i = socket.connectRead(SOCKET_SENSOR_MIN); // Читаем наличие датчика MIN.
    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 и отключит розетку.
    • Пример:
    socket.enableWDT( 5000 ); // Разрешаем работу сторожевого таймера розетки, задав ему время 5 секунд.
    

    Функция disableWDT();

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

    Функция resetWDT();

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

    Функция getStateWDT();

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

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

    Рассмотренные выше функции библиотеки iarduino_MB_Socket возвращают не только результат чтения, но и ошибки при записи или чтении. Причину ошибок можно выяснить функцией 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 = socket.setState(true );     // Включаем розетку (подаём напряжение с евровилки на розетку).
    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 - ошибка синтаксиса, означает наличие ошибки в коде, например функция вызвавшая данную ошибку была вызвана с некорректными параметрами, или вызвана до инициализации модуля.

    Ссылки:




    Обсуждение

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