Общие сведения:
Датчик кислотности жидкости (pH-метр) RS485 / Modbus с дисплеем и без дисплея - является устройством для измерения водородного показателя жидкости (показателя pH), характеризующего её кислотность, в диапазоне от 0 pH до 14 pH. Рассчитанную кислотность можно получать по протоколу Modbus шины RS485.
Датчик обеспечивает гальваническую развязку разъема щупа и разъема шины с питанием, что гарантирует отсутствие влияния и реакции щупа на другие устройства измерения жидкости.
Устройство можно использовать для анализа жидкостей используемых в аквариумах, системах водоснабжения, гидропонных установках и т.д. Датчик легко подключается сетевым кабелем через разъем RJ45.
В соответствии с протоколом Modbus, широко применяемому в промышленности, к одной шине RS485 можно подключить до 247 pH-метров. Адрес устройства (по умолчанию 0x04) назначается программно и хранится в его энергонезависимой памяти. Все устройства на шине должны иметь уникальный адрес.
Видео:
Спецификация:
- Напряжение питания: от 12 до 24 В постоянного тока (разъем RJ45).
 - Ток потребляемый датчиком: до 100 мА (при свечении всех сегментов дисплея).
 - Интерфейс: RS485 / Modbus.
 - Скорость шины: 4800 / 9600 / 19200 / 38400 / 57600 бит/с.
 - Настройки шины: 8N1 (8 бит данных, без проверки чётности, 1 стоп-бит).
 - Адрес на шине: устанавливается программно (по умолчанию 0x04).
 - Диапазон измерений водородного показателя: от 0 до 14 pH
 - Рабочая температура: от 0 до +60 °С.
 - Габариты: 100 x 70 x 40 мм.
 - Вес: ? г.
 

Подключение:
Важно: Перед подключением устройства к шине RS485 нужно отключить питание.
Так называемое «горячее подключение» может повредить устройство!
На корпусе датчика pH-метра имеется 2 разъёма: RJ45 и BNC:

- Разъем RJ45 - для подключения датчика к контроллеру по шине RS485.
 - Разъем BNC - для подключения измерительного щупа.
 
Назначение выводов разъема 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:
- HL-1 «BLINK» Индикатор включения:
 - Индикатор коротко мигает раз в две секунды -
значит устройство работает, но не получило ни 1 запроса с подачи питания. - Индикатор медленно мигает раз в секунду -
значит устройство работает, но последний запрос принят более 10 сек. назад. - Индикатор часто мигает пять раз в секунду -
значит устройство работает и последний запрос принят менее 10 сек. назад. - HL-2 «DATA» Индикатор получения запроса и обнаружения устройства:
 - Индикатор включается при получении запросов, что позволяет визуально отследить их поступление.
 - Устройству можно отправить команду на постоянное свечение индикатора, что позволит визуально найти устройство с известным адресом среди одинаковых устройств на шине.
 
Назначение выводов разъёма BNC:

- 1: «IN» - Вывод щупа на котором датчик устанавливает потенциал 1/2 Vcc = 1,65 В
 - 2: «OUT» - Вывод щупа с которого сигнал поступает на вход микросхемы АЦП.
 - Потенциалы разъема BNC гальванически развязаны с потенциалами разъема RJ45.
 
Если к разъёму BNC подключить щуп и погрузить его в нейтральную жидкость 7.0 pH, то между выводами 1 и 2 не будет разности потенциалов, что подано на вывод 1, то и придёт с вывода 2.
Щуп поставляемый с датчиком имеет чувствительность 59,16 мВ/pH. Это значит, что изменение кислотности на 1pH приводит к изменению разности потенциалов между выводами на 59,16 мВ. Но входное сопротивление микросхемы АЦП частично шунтирует напряжение щупа и снижает его чувствительность до 30 мВ/pH.
Значит при погружении щупа в жидкость 6.0 pH, на выводе 2 будет потенциал 1,65+0,03=1,68В, а при погружении щупа в жидкость 8.0 pH, на выводе 2 будет потенциал 1,65-0,03 = 1,62В.
Стоит учесть, что измерительный щуп является расходным материалом. Его характеристики со временем ухудшаются, уменьшается чувствительность и сдвигается потенциал нейтральной кислотности. Калибровка позволяет датчику определить текущие характеристики щупа, сохранить их в энергонезависимую память и использовать в дальнейших расчётах.
Питание:
Входное напряжение питания датчика от 12 до 24В постоянного тока подаётся через разъем PJ45. Датчик сохраняет работоспособность при снижении питания до 5В. Не подавайте питание выше 24В.
Подробнее о датчике:
Датчик кислотности жидкости (pH-метр) RS485 / Modbus построен на базе микроконтроллера STM32G030F4, микросхемы АЦП CS1237 и конвертера SN65HVD3082EDR с цепями защиты шины RS485 и встроенным терминатором, который можно отключать переключателем на плате. В устройстве используется несколько DC-DC преобразователей и стабилизаторы питания. Наличие гальванической развязки по линиям питания и линиям данных гарантирует, что измерительный щуп pH-метра не будет реагировать на другие устройства измерения жидкости подключённые к той же шине RS485.
Датчик с дисплеем оснащен четырёхразрядным LED дисплеем для отображается кислотности в режиме реального времени.
Датчик без дисплея оснащен зуммером для подачи сигналов о ошибках и стадиях калибровки.
Датчики способны работать с различными измерительными щупами, подключаемыми к разъему BNC, калибровка которых осуществляется всего одним нажатием на кнопку.
Принцип действия pH-метра основан на измерении величины ЭДС электродной системы, значение которой пропорционально водородному показателю pH = -Lg[H+]. Устройство считывает разницу потенциалов между выводами щупа, преобразуя полученные данные в отклонение водородного показателя жидкости от нейтрального значения 7,0 pH.
Датчик позволяет:
- Менять свой адрес на шине.
 - Менять тип протокола Modbus (RTU/ASCII).
 - Менять скорость передачи данных.
 - Сохранять одно двухбайтное слово в энергонезависимую память и читать его.
 - Читать гальванически развязанные напряжения с разных узлов схемы.
 - Управлять светодиодом обнаружения устройства на разъеме RJ45.
 - Запускать и контролировать процесс калибровки измерительного щупа.
 - Получать результаты калибровки и менять их вручную.
 - Задавать кислотности жидкостей используемых для калибровки.
 - Получать водородный показатель исследуемой жидкости.
 
Для работы с датчиком кислотности жидкости (pH-метр) RS485 / Modbus с дисплеем и без дисплея,  предлагаем воспользоваться разработанными нами библиотеками iarduino_Modbus и iarduino_MB_pH. Первая позволяет работать по протоколу Modbus на шине RS485, а вторая предназначена для работы с датчиком pH-метра.
Подробнее про установку библиотек читайте в нашей инструкции.
Примеры:
- Предложенные библиотеки содержат больше примеров, доступных из меню Arduino IDE:
 - Файл / Примеры / iarduino Modbus (протокол) / ModbusClient / HardwareSerial.
 - Файл / Примеры / iarduino Modbus (протокол) / ModbusClient / SoftwareSerial.
 - Файл / Примеры / iarduino Modbus pH (pH-метр) / HardwareSerial.
 - Файл / Примеры / iarduino Modbus pH (pH-метр) / 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 (назначается в скетче).

Trema конвертер UART-RS485 позволяет использовать датчик с дисплеем, без подключения к контроллеру (Arduino). Нужно подать питание на колодку Vin конвертера, а выводы TX, RX, G, V, D оставить без подключения. Получается схема визуального контроля за кислотностью жидкости.

В примерах ниже, для создания шины RS485, будет использована аппаратная шина UART1 (класс Serial1). Если у вашей платы Arduino нет свободных аппаратных шин UART, используйте программную шину UART при помощи входящей в состав Arduino IDE библиотеки SoftwareSerial.
Смена адреса датчика на шине:
Пример меняет текущий адрес датчика (nowAddress) на новый (newAddress) и сохраняет его в энергонезависимую память датчика, значит адрес сохранится и после отключения питания.
uint8_t nowAddress = 4;                     // Текущий адрес pH-метра ( 1 - 247 ).
uint8_t newAddress = 10;                    // Новый адрес pH-метра ( 1 - 247 ).
uint8_t pinDE      = 2;                     // Вывод DE конвертера UART-RS485.
                                            //
#include <iarduino_Modbus.h>                // Подключаем библиотеку для работы по протоколу Modbus.
#include <iarduino_MB_pH.h>                 // Подключаем библиотеку для работы с датчиком pH-метра.
                                            //
ModbusClient modbus(Serial1, pinDE);        // Создаём объект для работы по протоколу Modbus указав шину UART-RS485 и вывод DE.
iarduino_MB_pH sensor(modbus);              // Создаём объект для работы с pH-метром указав объект протокола 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 =    sensor.begin(nowAddress);       // Инициируем работу с датчиком pH-метра, указав его текущий адрес nowAddress.
     if(f){ Serial.println("OK");  }        // Если f=true значит инициализация пройдена успешно.
     else { Serial.println("ERR"); }        // Если f=false значит инициализация не пройдена.
     Serial.print("Смена адреса ");         //
     f =    sensor.changeID(newAddress);    // Меняем адрес датчика pH-метра на новый newAddress.
     if(f){ Serial.println("OK");  }        // Если f=true значит адрес изменён.
     else { Serial.println("ERR"); }        // Если f=false значит адрес не изменён.
     Serial.print("Текущий адрес ");        //
     Serial.println(sensor.getID());        // Выводим текущий адрес датчика pH-метра.
     Serial.print("Версия прошивки ");      //
     Serial.println(sensor.getVersion());   // Выводим версию прошивки датчика pH-метра.
}                                           //
                                            //
void loop(){                                // Визуально показываем у какого устройства был изменён адрес.
     sensor.setIDLED(true ); delay(1000);   // Включаем светодиодом обнаружения устройства (на разъёме RJ45).
     sensor.setIDLED(false); delay(1000);   // Выключаем светодиодом обнаружения устройства (на разъёме RJ45).
}                                           //
Пример будет более коротким, если убрать вывод данных в монитор последовательного порта и обращаться к функциям sensor.begin(), sensor.changeID() без проверки f. Если при обращении к функции sensor.begin() не указывать текущий адрес датчика nowAddress, то он будет найден автоматически, но это займёт некоторое время.
Чтение кислотности жидкости:
Пример выводит показания кислотности в монитор последовательного порта.
uint8_t pinDE = 2;                          // Вывод DE конвертера UART-RS485.
                                            //
#include <iarduino_Modbus.h>                // Подключаем библиотеку для работы по протоколу Modbus.
#include <iarduino_MB_pH.h>                 // Подключаем библиотеку для работы с датчиком pH-метра.
                                            //
ModbusClient modbus(Serial1, pinDE);        // Создаём объект для работы по протоколу Modbus указав шину UART-RS485 и вывод DE.
iarduino_MB_pH sensor(modbus);              // Создаём объект для работы с pH-метром указав объект протокола Modbus.
                                            //
void setup(){                               //
     Serial.begin(9600); while(!Serial);    // Инициируем передачу данных в монитор последовательного порта, указав его скорость.
     Serial1.begin(9600); while(!Serial1);  // Инициируем работу с шиной UART-RS485 указав её скорость.
     modbus.begin();                        // Инициируем работу по протоколу Modbus.
//   modbus.setTimeout(10);                 // Указываем максимальное время ожидания ответа по протоколу Modbus.
//   modbus.setDelay(4);                    // Указываем минимальный интервал между отправляемыми сообщениями по протоколу Modbus.
//   modbus.setTypeMB( MODBUS_RTU );        // Указываем тип протокола Modbus: MODBUS_RTU (по умолчанию), или MODBUS_ASCII.
     bool f = sensor.begin(4);              // Инициируем работу с датчиком pH-метра, указав его адрес.
     if( !f ){                              // Если функция begin() вернула false, значит датчик pH-метра с адресом 4 не найден.
         Serial.print("pH-метр не найден"); //
         while(1);                          // Запрещаем дальнейшее выполнение скетча.
     }                                      //
}                                           //
                                            //
void loop(){                                //
     delay(1000);                           //
//   Получаем кислотность жидкости:         //
     float pH = sensor.getPH();             // Получаем кислотность жидкости.
//   Выводим результат:                     //
     if( pH<0 ){ Serial.println("Err"); }   // Сообщаем о ошибке чтения.
     else      { Serial.println(pH, 1); }   // Выводим полученный водородный показатель жидкости с одним знаком после запятой.
}                                           //
Этот пример кажется большим, но если убрать все проверки и некоторые комментарии, то код будет более компактным.
Пример выводит показания кислотности без проверок инициализации и чтения:
#include <iarduino_Modbus.h>                // Подключаем библиотеку для работы по протоколу Modbus.
#include <iarduino_MB_pH.h>                 // Подключаем библиотеку для работы с датчиком pH-метра.
                                            //
ModbusClient modbus(Serial1, 2);            // Создаём объект для работы по протоколу Modbus указав шину UART-RS485 и вывод DE.
iarduino_MB_pH sensor(modbus);              // Создаём объект для работы с pH-метром указав объект протокола Modbus.
                                            //
void setup(){                               //
     Serial.begin(9600); while(!Serial);    // Инициируем передачу данных в монитор последовательного порта, указав его скорость.
     Serial1.begin(9600); while(!Serial1);  // Инициируем работу с шиной UART-RS485 указав её скорость.
     modbus.begin();                        // Инициируем работу по протоколу Modbus.
     sensor.begin(4);                       // Инициируем работу с pH-метром, указав его адрес.
}                                           // Если адрес не указан sensor.begin(), то он будет найден, но это займёт некоторое время.
                                            //
void loop(){                                //
     delay(1000);                           //
     Serial.println(sensor.getPH(), 1);     // Выводим полученный водородный показатель жидкости с одним знаком после запятой.
}                                           //
Несмотря на то, что код без проверок кажется более понятным, рекомендуется выполнять проверки, так как это помогает отслеживать ошибки в процессе работы устройства.
Чтение кислотности жидкости с проверкой на наличие ошибок:
Пример позволяет не только прочитать кислотность жидкости, но и проверить её корректность.
uint8_t pinDE = 2;                          // Вывод DE конвертера UART-RS485.
                                            //
#include <iarduino_Modbus.h>                // Подключаем библиотеку для работы по протоколу Modbus.
#include <iarduino_MB_pH.h>                 // Подключаем библиотеку для работы с датчиком pH-метра.
                                            //
ModbusClient modbus(Serial1, pinDE);        // Создаём объект для работы по протоколу Modbus указав шину UART-RS485 и вывод DE.
iarduino_MB_pH sensor(modbus);              // Создаём объект для работы с pH-метром указав объект протокола Modbus.
                                            //
void setup(){                               //
     Serial.begin(9600); while(!Serial);    // Инициируем передачу данных в монитор последовательного порта, указав его скорость.
     Serial1.begin(9600); while(!Serial1);  // Инициируем работу с шиной UART-RS485 указав её скорость.
     modbus.begin();                        // Инициируем работу по протоколу Modbus.
//   modbus.setTimeout(10);                 // Указываем максимальное время ожидания ответа по протоколу Modbus.
//   modbus.setDelay(4);                    // Указываем минимальный интервал между отправляемыми сообщениями по протоколу Modbus.
//   modbus.setTypeMB( MODBUS_RTU );        // Указываем тип протокола Modbus: MODBUS_RTU (по умолчанию), или MODBUS_ASCII.
     bool f = sensor.begin(4);              // Инициируем работу с датчиком pH-метра, указав его адрес.
     if( !f ){                              // Если функция begin() вернула false, значит датчик pH-метра с адресом 4 не найден.
         Serial.print("pH-метр не найден"); //
         while(1);                          // Запрещаем дальнейшее выполнение скетча.
     }                                      //
}                                           //
                                            //
void loop(){                                //
     delay(1000);                           //
//   Получаем данные от датчика:            //
     float   pH   = sensor.getPH();         // Получаем кислотность жидкости.
     int32_t err  = sensor.getErr();        // Получаем ошибки диагностики (датчик постоянно проводит самодиагностику).
     int8_t  stab = sensor.getStability();  // Получаем флаг нормализации показаний кислотности (указывает что pH не меняется).
//   Информируем о отсутствии ответа:       //
     if( pH<0 || err<0 || stab<0 ){         //
         Serial.println( "Нет ответа." );   // Сообщаем о ошибке чтения.
         return;                            // Переходим к следующему проходу цикла loop.
     }                                      //
//   Информируем о наличии ошибок:          //
     if( err                   ){ Serial.print( F("Показания не точны! "                ) ); } //   Если есть ошибки.
     if( err & ERR_MB_pH_Power ){ Serial.print( F("Стабилизация после подачи питания. " ) ); } //   Прибору требуется время для стабилизации показаний после подачи питания.
     if( err & ERR_MB_pH_Data  ){ Serial.print( F("Ошибка чтения данных из АЦП. "       ) ); } //   Чип АЦП на плате датчика не отвечает.
     if( err & ERR_MB_pH_Jumps ){ Serial.print( F("Значение pH 'скачет'. "              ) ); } //   Возможно плохой контакт на разъёме щупа или прибор не откалиброван.
     if( err & ERR_MB_pH_Vin   ){ Serial.print( F("Некорректное напряжение на щупе. "   ) ); } //   Напряжение подаваемое на щуп вышло за допустимый диапазон.
     if( err & ERR_MB_pH_Vout  ){ Serial.print( F("Некорректное напряжение от щупа. "   ) ); } //   Напряжение снимаемое с щупа вышло за допустимый диапазон.
     if( err & ERR_MB_pH_5V    ){ Serial.print( F("Низкое напряжение питания 5В. "      ) ); } //   Стабилизированное напряжение питания 5В < 4В. Стабильная работа не гарантируется.
     if( err & ERR_MB_pH_Init  ){ Serial.print( F("Ошибка инициализации АЦП. "          ) ); } //   Настройка АЦП на плате датчика не выполнена.
//   Выводим результат:                     //
     Serial.print( "Кислотность ");         //
     Serial.print( pH, 1 );                 // Выводим полученный водородный показатель жидкости, с одним знаком после запятой.
     Serial.print( " pH" );                 //
//   Выводим анализ стабильности:           //
     if( stab ){                            //
         Serial.println( ", стабильна." );  // Информируем о стабильности показаний (pH не меняется).
     }else{                                 //
         Serial.println( " и меняется." );  // Информируем о не стабильности показаний (pH меняется).
     }                                      //
}                                           //
Этот пример, как и два предыдущих, получает кислотность жидкости sensor.getPH(), но еще проверяет наличие ошибок sensor.getErr() и выводит флаг стабильности кислотности жидкости sensor.getStability().
Датчик проводит самодиагностику в режиме реального времени и при обнаружении ошибок, выводит соответствующие сообщения на дисплей.
Дисплей:
Данный раздел относится только с датчику с дисплеем.
Четырёхразрядный LED дисплей выводит кислотность жидкости и информирует о ошибках.
![]()  | Стабилизация показаний после подачи питания (30 сек). Удержание кнопки «Калибровка».  | 
![]()  | Основной режим работы. Дисплей выводит кислотность исследуемой жидкости.  | 
![]()  | Ошибка 0. Провал инициализации чипа АЦП. Попробуйте отключить и вновь подать питание на датчик.  | 
![]()  | Ошибка 1. Ошибка возникает при низком напряжении питания. Проверьте питание и разъём RJ-45.  | 
![]()  | Ошибка 2. На щуп подано напряжение ниже требуемого. Датчик неисправен.  | 
![]()  | Ошибка 3. На щуп подано напряжение выше требуемого. Датчик неисправен.  | 
![]()  | Ошибка 4. Высокая разница потенциалов на выводах щупа pH<0. Возможно щуп не подключён или неисправен.  | 
![]()  | Ошибка 5. Высокая разница потенциалов на выводах щупа pH>14. Возможно щуп не подключён или неисправен.  | 
![]()  | Ошибка 6. Некорректные показания кислотности. Данные "скачут". Неисправен щуп или некорректны калибровочные значения.  | 
![]()  | Ошибка 7. Ошибка чтения данных с чипа АЦП. Датчик неисправен.  | 
![]()  | Ошибка С (Error Calibration). Ошибка калибровки. Выполнена с ошибкой или прервана.  | 
Зуммер:
Датчик без дисплея позволяет информировать о ошибках подачей звуковых сигналов.
| Ошибка 0 | • | Провал инициализации чипа АЦП. Каждую секунду датчик издаёт один короткий звуковой сигнал.  | 
| Ошибка 1 | ─ | Низкое напряжение питания. Каждую секунду датчик издаёт один длинный звуковой сигнал.  | 
| Ошибка 2 | • • | На щуп подано напряжение ниже требуемого. Каждую секунду датчик издаёт два коротких звуковых сигнала.  | 
| Ошибка 3 | ─ ─ | На щуп подано напряжение выше требуемого. Каждую секунду датчик издаёт два длинных звуковых сигнала.  | 
| Ошибка 4 | • ─ | Высокая разница потенциалов на выводах щупа pH<0. Каждую секунду датчик издаёт два сигнала, короткий, потом длинный.  | 
| Ошибка 5 | ─ • | Высокая разница потенциалов на выводах щупа pH>14. Каждую секунду датчик издаёт два сигнала, длинный, потом короткий.  | 
| Ошибка 6 | • • ─ | Некорректные показания кислотности. Данные "скачут". Каждую секунду датчик издаёт три сигнала, 2 коротких и 1 длинный.  | 
| Ошибка 7 | ─ • • | Ошибка чтения данных с чипа АЦП. Каждую секунду датчик издаёт три сигнала, 1 длинный и 2 коротких.  | 
| Ошибка С | ─ ─ ─ | Калибровка выполнена с ошибкой или прервана. Датчик издаёт три очень длинных звуковых сигнала.  | 
Сигналы о ошибках генерируются на низкой (500Гц) частоте.
Длительность короткого сигнала составляет 0,1 сек, длинного 1 сек, а очень длинного 2 сек.
Калибровка:
Для калибровки потребуются две калибровочные жидкости, с водородными показателями 4,0 pH и 9.18 pH, а так же дистиллированная вода. Все жидкости должны иметь температуру при которой планируется выполнять дальнейшие измерения.
Примечание: Для калибровки датчика можно использовать жидкости с другими водородными показателями если их предварительно указать функцией setKnownPH() библиотеки iarduino_MB_pH.
Водородный показатель первой калибровочной жидкости должен отличаться от второй не менее чем на 2 pH.
Перед калибровкой очистите щуп от жидкости в которой он был ранее. Для этого опустите щуп в стакан с дистиллированной водой, поводите щупом споласкивая его, достаньте щуп и встряхните, избавившись от крупных капель.
Калибровка датчика с дисплеем:
![]()  | Запуск калибровки. Опустите щуп в первую жидкость (4,0 pH). Удерживайте кнопку «Калибровка» до появления «----».  | 
![]()  | 1 стадия калибровки (ожидание). На дисплее появится требуемый pH первой жидкости (4,00). Датчик ждёт стабилизации показаний измерительного щупа.  | 
![]()  | 1 стадия калибровки (выполнение). Датчик считывает показания измерительного щупа и выводит на дисплей анимацию кругового включения сегментов.  | 
![]()  | Ожидание смены жидкости. На дисплее мигает требуемый pH второй жидкости (9,18). Достаньте щуп из первой жидкости и опустите во вторую. Датчик сам определит смену жидкости.  | 
![]()  | 2 стадия калибровки (ожидание). Требуемый водородный показатель перестанет мигать. Датчик ждёт стабилизации показаний измерительного щупа.  | 
![]()  | 2 стадия калибровки (выполнение). Датчик считывает показания измерительного щупа и выводит на дисплей анимацию кругового включения сегментов.  | 
![]()  | Успешное завершение калибровки. Если на дисплее появилась надпись «Good», значит калибровка выполнена успешно и все рассчитанные показания сохранены в энергонезависимую память датчика.  | 
![]()  | Ошибка калибровки. Если на дисплее появилась надпись «Err.C» значит калибровка не выполнена и данные не сохранены. Результат калибровки (Good / Err.C) исчезнет через 2 секунды.  | 
Калибровка датчика без дисплея:
| • | Запуск калибровки. Опустите щуп в первую калибровочную жидкость (4,00 pH). Нажмите и удерживайте кнопку «Калибровка». Датчик издаст короткий звуковой сигнал при нажатии на кнопку и такой же сигнал через секунду её удержания, тогда кнопку можно отпустить.  | 
| • | 1 стадия калибровки. Каждую секунду датчик издаёт один короткий звуковой сигнал. На этой стадии датчик ждёт стабилизации показаний щупа, а потом считывает их.  | 
| ─ ─ | Ожидание смены жидкости. Каждую секунду датчик издаёт два длинных звуковых сигнала. Достаньте щуп из первой калибровочной жидкости и опустите во вторую.  | 
| • • | 2 стадия калибровки. Каждую секунду датчик издаёт два коротких звуковых сигнала. На этой стадии датчик ждёт стабилизации показаний щупа, а потом считывает их.  | 
| ─ | Успешное завершение калибровки. Если датчик издал один очень длинный звуковой сигнал, значит калибровка выполнена успешно и все рассчитанные показания сохранены в энергонезависимую память.  | 
| ─ ─ ─ | Ошибка калибровки. Если датчик издал три очень длинных звуковых сигнала, значит калибровка не выполнена и данные не сохранены.  | 
Сигналы о стадиях и успехе калибровки генерируются на высокой (3кГц) частоте, а сигнал о ошибке, на низкой (500Гц) частоте.
Длительность короткого сигнала составляет 0,1 сек, длинного 1 сек, а очень длинного 2 сек.
Правила калибровки общие для датчиков с дисплеем и без:
Запустить калибровку можно не только удержанием кнопки «Калибровка», но и обращением к функции setCalibration() библиотеки iarduino_MB_pH.
После запуска калибровки, требуется только сменить первую калибровочную жидкость на вторую. Датчик самостоятельно зафиксирует смену жидкости и перейдёт ко второй стадии.
При смене калибровочных жидкостей рекомендуется сполоснуть щуп в дистиллированной воде, чтоб остатки первой калибровочной жидкости не попали во вторую.
Процесс ожидания стабилизации показаний щупа занимает не менее 10 секунд.
Калибровку можно отменить, в любой момент, повторным нажатием на кнопку «Калибровка». Калибровка автоматически отменяется, если любая из стадий калибровки выполняется дольше 2 минут. Отмена калибровки расценивается как ошибка с соответствующим уведомлением.
Библиотека iarduino_MB_pH позволяет запускать калибровку, определять стадии калибровки, получать результат калибровки, читать и менять данные рассчитанные при калибровке, а так же указывать pH используемых калибровочных жидкостей.
Описание функций библиотеки:
В данном разделе описаны функции библиотеки iarduino_MB_pH для работы с датчиком кислотности жидкости (pH-метр) 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_pH.h>       // Подключаем библиотеку для работы с датчиком pH-метра.
                                  //
ModbusClient   modbus(Serial, 2); // Создаём объект для работы по протоколу Modbus указав класс Serial и номер вывода DE конвертера UART-RS485.
iarduino_MB_pH sensor(modbus);    // Создаём объект для работы с pH-метром указав объект протокола Modbus.
                                  //
void setup(){                     //
     ...                          //
     Serial.begin(9600);          // Указываем скорость шины RS485. Она равна скорости шины UART подключённой к конвертеру UART-RS485.
     while(!Serial);              //
     sensor.begin(4);             // Инициируем работу с pH-метром, указав его адрес.
     ...                          // Если адрес не указан sensor.begin(), то он будет найден, но это займёт некоторое время.
}                                 //
Если используется аппаратная шина UART-1, то вместо класса Serial указываем Serial1, для шины UART2 указываем Serial2 и т.д.
- Если используется программная реализация шины UART:
 
#include <SoftwareSerial.h>       // Подключаем библиотеку для работы с программной шиной UART.
#include <iarduino_Modbus.h>      // Подключаем библиотеку для работы по протоколу Modbus.
#include <iarduino_MB_pH.h>       // Подключаем библиотеку для работы с датчиком pH-метра.
                                  //
SoftwareSerial rs485(8, 9);       // Создаём объект для работы с программной шиной UART указывая выводы RX, TX.
ModbusClient   modbus(rs485, 2);  // Создаём объект для работы по протоколу Modbus указав объект программной шины UART и номер вывода DE конвертера UART-RS485.
iarduino_MB_pH sensor(modbus);    // Создаём объект для работы с pH-метром указав объект протокола Modbus.
                                  //
void setup(){                     //
     ...                          //
     rs485.begin(9600);           // Указываем скорость шины RS485. Она равна скорости программной шины UART подключённой к конвертеру UART-RS485.
     while(!rs485);               //
     sensor.begin(4);             // Инициируем работу с pH-метром, указав его адрес.
     ...                          // Если адрес не указан sensor.begin(), то он будет найден, но это займёт некоторое время.
}                                 //
Для программной реализации шины UART необходимо указать выводы которые будут использоваться как RX и TX, в примере указаны выводы 8, и 9 соответственно. При создании объекта modbus указывается не класс Serial, а объект для работы с программной шиной UART.
Скорость передачи данных по шине Modbus равна скорости шины UART.
Функция begin();
- Назначение: Инициализация работы с датчиком pH-метра.
 - Синтаксис: begin( [ АДРЕС_ДАТЧИКА ] );
 - Параметр: uint8_t АДРЕС_ДАТЧИКА - значение от 1 до 247.
 - Возвращаемое значение: bool - результат инициализации (true или false).
 - Примечание:
 - Если вызвать функцию без параметра, то адрес pH-метра будет найден автоматически. На это уйдёт некоторое время и на шине долен быть только один датчик pH-метра.
 - Функцию достаточно вызвать 1 раз в коде Setup(), до обращения к остальным функциям библиотеки.
 - Датчики pH-метров поставляются с адресом 4 на шине, но этот адрес можно изменить.
 - Пример:
 
sensor.begin(4); // Инициируем работу с pH-метром, указав его адрес на шине.
Функция reset();
- Назначение: Программная перезагрузка датчика pH-метра.
 - Синтаксис: reset();
 - Параметры: Нет.
 - Возвращаемое значение: bool - результат перезагрузки (true или false).
 - Пример:
 
sensor.reset(); // Выполняем программную перезагрузку.
Функция changeID();
- Назначение: Установка нового адреса на шине.
 - Синтаксис: changeID( АДРЕС_ДАТЧИКА );
 - Параметр: uint8_t АДРЕС_ДАТЧИКА - значение от 1 до 247.
 - Возвращаемое значение: bool - результат изменения адреса (true или false).
 - Примечание:
 - Новый адрес сохраняется в энергонезависимую память, а значит остаётся после отключения питания.
 - Выполнение функции занимает более 120 миллисекунд.
 - Пример:
 
sensor.changeID(10); // Изменить адрес датчика на значение 10.
Функция setSpeedMB();
- Назначение: Установка новой скорости передачи данных.
 - Синтаксис: setSpeedMB( СКОРОСТЬ );
 - Параметр: uint32_t СКОРОСТЬ - может принимать одно из значений:
4800 / 9600 / 19200 / 38400 / 57600. - Возвращаемое значение: bool - результат изменения скорости (true или false).
 - Примечание:
 - Новая скорость применяется на 2 секунды, в течении которых её нужно подтвердить.
 - Если скорость не подтвердить в течении 2 секунд, датчик вернёт прежнюю скорость.
 - Скорость подтверждается функцией ackSpeedMB() на новой скорости шины.
 
Функция ackSpeedMB();
- Назначение: Подтверждение смены скорости передачи данных.
 - Синтаксис: ackSpeedMB();
 - Параметры: Нет.
 - Возвращаемое значение: bool - результат подтверждения скорости (true или false).
 - Примечание:
 - Подтверждение скорости выполняется после установки новой скорости датчика функцией setSpeedMB() и установки той же скорости для шины UART-RS485.
 - Если скорость не подтвердить в течении 2 секунд, датчик вернёт прежнюю скорость.
 - Подтверждённая скорость сохраняется в энергонезависимую память, а значит остаётся после отключения питания.
 - Выполнение функции занимает более 50 миллисекунд.
 - Пример:
 
sensor.setSpeedMB(9600); // Изменить скорость датчика на 9600 бит/сек. Serial.begin(9600); // Изменить скорость шины UART-RS485 на 9600 бит/сек. sensor.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 миллисекунд.
 - Пример:
 
sensor.setTypeMB(MODBUS_RTU); // Изменить тип протокола датчика на Modbus RTU. modbus.setTypeMB(MODBUS_RTU); // Изменить тип протокола шины UART-RS485 на Modbus RTU. sensor.ackTypeMB(); // Подтвердить тип протокола датчика.
Функция writeFlash();
- Назначение: Запись пользовательского значения в Flash память.
 - Синтаксис: writeFlash( ЧИСЛО );
 - Параметр: uint16_t ЧИСЛО - любое значение от 0 до 65535.
 - Возвращаемое значение: bool - результат записи (true или false).
 - Примечание:
 - Записываемое число сохраняется в энергонезависимую память, а значит остаётся после отключения питания.
 - Выполнение функции занимает более 50 миллисекунд.
 - Для чтения числа из Flash памяти воспользуйтесь функцией readFlash().
 - Число хранится в регистре "Holding Registers" [0x0120] «USER_DATA».
 - Пример:
 
sensor.writeFlash(12345); // Записать число в энергонезависимую память.
Функция readFlash();
- Назначение: Чтение пользовательского значения из Flash памяти.
 - Синтаксис: readFlash();
 - Параметры: Нет.
 - Возвращаемое значение: int32_t - число из памяти (0...65535) , или -1 при провале чтения.
 - Примечание:
 - Для записи числа в Flash память воспользуйтесь функцией writeFlash().
 - Число хранится в регистре "Holding Registers" [0x0120] «USER_DATA».
 - Пример:
 
i = sensor.readFlash();         // Читаем число из энергонезависимой памяти.
if(i<0){ Serial.print("ERR"); } // Сообщаем о ошибке.
else   { Serial.print(  i  ); } // Выводим прочитанное значение.
Функция getID();
- Назначение: Чтение адреса устройства на шине.
 - Синтаксис: getID();
 - Параметры: Нет.
 - Возвращаемое значение: uint8_t - адрес (1...247), или 0 если устройство не инициировано.
 - Примечание:
 - Данная функция может пригодиться если инициализация устройства выполнена функцией begin() без указания адреса (адрес найден автоматически).
 - Пример:
 
i = sensor.getID();              // Читаем адрес устройства на шине.
if(i==0){ Serial.print("ERR"); } // Сообщаем о ошибке.
else    { Serial.print(  i  ); } // Выводим адрес устройства на шине.
Функция getVersion();
- Назначение: Чтение версии прошивки устройства.
 - Синтаксис: getVersion();
 - Параметры: Нет.
 - Возвращаемое значение: uint8_t - версия прошивки, или 0 если устройство не инициировано.
 - Пример:
 
i = sensor.getVersion();         // Читаем версию прошивки устройства.
if(i==0){ Serial.print("ERR"); } // Сообщаем о ошибке.
else    { Serial.print(  i  ); } // Выводим версию прошивки устройства.
Функция setIDLED();
- Назначение: Управление индикатором обнаружения устройства.
 - Синтаксис: setIDLED( СОСТОЯНИЕ );
 - Параметр: bool СОСТОЯНИЕ - флаг включения индикатора (true или false).
 - Возвращаемое значение: bool - результат применения состояния индикатора (true или false).
 - Примечание:
 - Индикатор обнаружения устройства - это светодиод на разъеме RJ-45.
 - Если индикатор включён, то светодиод постоянно светится. Так можно визуально определить устройство, если на шине имеются несколько одинаковых устройств.
 - Если индикатор отключен, то светодиод информирует о получении запросов, адресованных этому устройству.
 - Пример:
 
sensor.setIDLED(true ); // Включаем индикатор обнаружения устройства. sensor.setIDLED(false); // Отключаем индикатор обнаружения устройства.
Функция getPWR();
- Назначение: Чтение напряжения питания на шине 5V.
 - Синтаксис: getPWR();
 - Параметры: Нет.
 - Возвращаемое значение: float - напряжение (00,000...65,535 В), или -1 при провале чтения.
 - Примечание:
 - Данная функция позволяет узнать напряжение питания на гальванически развязанной шине питания 5V.
 - У других модулей iarduino, не имеющих гальванической развязки по питанию, данная функция возвращает напряжение питания получаемое с разъема RJ45.
 - Пример:
 
i = sensor.getPWR();            // Читаем гальванически развязанное напряжение питания 5V.
if(i<0){ Serial.print("ERR"); } // Сообщаем о ошибке.
else   { Serial.print(  i  ); } // Выводим напряжение питания шины 5V в вольтах.
Функция getErr();
- Назначение: Чтение флагов ошибок из регистра диагностики.
 - Синтаксис: getErr();
 - Параметры: Нет.
 - Возвращаемое значение: int32_t - регистр диагностики (2 байта), или -1 при провале чтения.
 - Примечание:
 - Функция возвращает двухбайтное значение из регистра диагностики.
 - Каждый бит регистра диагностики информирует о ошибке.
 - Датчик постоянно проводит самодиагностику в режиме реального времени.
 - Пример:
 
i = sensor.getErr();    //                Получаем значение регистра диагностики.
if( i                   ){ Serial.print( "Есть ошибки: "                        ); }
if( i & ERR_MB_pH_Power ){ Serial.print( "Стабилизация после подачи питания. "  ); }
if( i & ERR_MB_pH_Data  ){ Serial.print( "Ошибка чтения данных из АЦП. "        ); }
if( i & ERR_MB_pH_Jumps ){ Serial.print( "Значение pH 'скачет'. "               ); }
if( i & ERR_MB_pH_Vin   ){ Serial.print( "Некорректное напряжение на щупе. "    ); }
if( i & ERR_MB_pH_Vout  ){ Serial.print( "Некорректное напряжение от щупа. "    ); }
if( i & ERR_MB_pH_5V    ){ Serial.print( "Низкое напряжение питания 5В шины. "  ); }
if( i & ERR_MB_pH_Init  ){ Serial.print( "Ошибка инициализации АЦП. "           ); }
Функция setCalibration();
- Назначение: Запуск калибровки.
 - Синтаксис: setCalibration();
 - Параметры: Нет.
 - Возвращаемое значение: bool - результат запуска калибровки (true или false).
 - Примечание:
 - Обращение к функции равносильно нажатию на кнопку "Калибровка".
 - Перед запуском нужно сполоснуть щуп и опустить его в 1 калибровочную жидкость.
 - Узнать текущую стадию калибровки можно функцией getCalibration().
 - Пример:
 
sensor.setCalibration(); // Запускаем калибровку.
Функция getCalibration();
- Назначение: Чтение текущей стадии калибровки.
 - Синтаксис: getCalibration();
 - Параметры: Нет.
 - Возвращаемое значение: int8_t - стадия калибровки (0,1,2,3), или -1 при провале чтения.
 - Примечание:
 - Подробно о стадиях калибровки написано выше, в разделе "Калибровка".
 - Актуальные значения возвращаемые функцией:
 - 0 - Калибровка не выполняется.
 - 1 - Выполняется первая стадия калибровки.
 - 2 - Выполняется вторая стадия калибровки.
 - 3 - Датчик ожидает смены первой калибровочной жидкости на вторую.
 - Результат калибровки можно узнать функцией getResultCalib().
 - Пример:
 
    i = sensor.setCalibration();                      // Запускаем калибровку.
do{ j = sensor.getCalibration(); delay(1000);         // Читаем текущую стадию калибровки.
    if( j==1 ){ Serial.println("1 стадия..."     ); } // Выполняется 1 стадия калибровки.
    if( j==3 ){ Serial.println("смените жидкость"); } // Датчик ждёт смены жидкости.
    if( j==2 ){ Serial.println("2 стадия..."     ); } // Выполняется 2 стадия калибровки.
}while( j );                                          // Выполняем цикл пока выполняется калибровка.
Serial.println("Калибровка завершена"); }             // Эта строка выполнится если j==0.
Функция getResultCalib();
- Назначение: Чтение результата последней калибровки.
 - Синтаксис: getResultCalib();
 - Параметры: Нет.
 - Возвращаемое значение: int8_t - результат (true или false), или -1 при провале чтения.
 - Примечание:
 - Результат калибровки устанавливается в true при запуске калибровки.
 - Результат калибровки сбрасывается в false если калибровка выполнена с ошибкой.
 - Датчик считает калибровку выполненной с ошибкой,если рассчитанная чувствительность щупа выходит за диапазон 12...75 мВ/pH, или нейтральная кислотность для щупа выходит за диапазон ±3 pH от эталонного значения 7,00 pH. В таком случае результаты калибровки не сохраняются, а функция getResultCalib() возвращает false.
 - Пример:
 
       sensor.setCalibration();     // Запускаем калибровку.
while( sensor.getCalibration() )    // Выполняем цикл пока выполняется калибровка.
     { delay(1000);            }    // Не перегружаем шину.
i =    sensor.getResultCalib();     // Получаем результат калибровки.
if(i<0){ Serial.print("?"  ); }else // Датчик не ответил.
if( i ){ Serial.print("OK" ); }else // Калибровка завершена успешно.
       { Serial.print("ERR"); }     // Калибровка завершена с ошибкой.
Функция getStability();
- Назначение: Чтение флага нормализации показаний.
 - Синтаксис: getStability();
 - Параметры: Нет.
 - Возвращаемое значение: int8_t - флаг нормализации (true/false), или -1 при провале чтения.
 - Примечание:
 - Функция возвращает true если показания кислотности стабильны.
 - Функция возвращает false если кислотность увеличивается или уменьшается.
 - Показания кислотности считаются стабильными если её среднее значение за последние 10 секунд не сместилось за предел допустимой флуктуации.
 - Показания кислотности считаются нестабильными (увеличиваются или уменьшаются, если её среднее значение за последние 10 секунд сместилось за предел высокой флуктуации.
 - Функции setFluctuation() / getFluctuation() позволяют задавать / получать уровни допустимой и высокой флуктуации.
 - Пример:
 
i = sensor.getStability();      // Читаем флаг нормализации показаний.
if(i<0){ Serial.print("ERR"); } // Сообщаем о ошибке.
else   { Serial.print(  i  ); } // Выводим флаг.
Функция getPH();
- Назначение: Чтение кислотности исследуемой жидкости.
 - Синтаксис: getPH();
 - Параметры: Нет.
 - Возвращаемое значение: float - кислотность (0...14,000 pH), или -1 при провале чтения.
 - Пример:
 
i = sensor.getPH();             // Читаем кислотность.
if(i<0){ Serial.print("ERR"); } // Сообщаем о ошибке.
else   { Serial.print(  i  ); } // Выводим кислотность.
Функции настройки датчика:
В данном разделе описаны функции настройки работы датчика. Датчик использует различные коэффициенты и значения для вычислений. По умолчанию они установлены в стандартные значения и не требуют изменений.
Важно: Все значения устанавливаемые функциями настройки датчика сохраняются в энергонезависимую память датчика, а значит действуют и после отключения питания!
Функция setKnownPH();
- Назначение: Установка кислотности калибровочных жидкостей.
 - Синтаксис: setKnownPH( СТАДИЯ , КИСЛОТНОСТЬ );
 - Параметры:
 - uint8_t СТАДИЯ - может принимать значение 1 или 2.
 - float КИСЛОТНОСТЬ - может принимать значения от 0,000 до 14,000 pH.
 - Возвращаемое значение: bool - результат записи значения (true или false).
 - Примечание:
 - Калибровка производится с использованием двух калибровочных жидкостей, кислотность которых должна быть равна 4,00 и 9,18 pH (по умолчанию). Данная функция позволяет указать датчику, что для калибровки будут использоваться другие жидкости.
 - Первый параметр указывает, кислотность какой жидкости (1 или 2) мы сохраняем.
 - Второй параметр указывает, жидкость с какой кислотностью будет использоваться.
 - Кислотность первой калибровочной жидкости должна отличатся от кислотности второй калибровочной жидкости не менее чем на 2,00 pH (в любую сторону).
 - Указанные кислотности сохраняются в энергонезависимую память.
 - Выполнение функции занимает более 50 миллисекунд.
 - Пример:
 
sensor.setKnownPH(1, 5.00); // На 1 стадии калибровки будет жидкость 5.00 pH. sensor.setKnownPH(2, 9.00); // На 2 стадии калибровки будет жидкость 9.00 pH.
Функция getKnownPH();
- Назначение: Чтение кислотности жидкостей требуемых для калибровки.
 - Синтаксис: getKnownPH( СТАДИЯ );
 - Параметр: uint8_t СТАДИЯ - может принимать значение 1 или 2.
 - Возвращаемое значение: float - требуемая кислотность в pH, или -1 при провале чтения.
 - Примечание:
 - Функция позволяет узнать требуемые кислотности калибровочных жидкостей.
 - Параметр функции указывает, кислотность какой жидкости (1 или 2) требуется вернуть.
 - По умолчанию, для 1 стадии калибровки, требуется жидкость с кислотностью 4.00 pH.
 - По умолчанию, для 2 стадии калибровки, требуется жидкость с кислотностью 9.18 pH.
 - Пример:
 
i = sensor.getKnownPH( 1 ); // Читаем кислотность требуемую на 1 стадии калибровки.
j = sensor.getKnownPH( 2 ); // Читаем кислотность требуемую на 2 стадии калибровки.
if( i<0 || j<0 ){ Serial.print("Err"); }else{ Serial.print( (String) "1="+i+"pH, 2="+j+"pH." ); }
Функция setFluctuation();
- Назначение: Установка пределов флуктуации кислотности.
 - Синтаксис: setFluctuation( ТИП , КИСЛОТНОСТЬ );
 - Параметры:
 - uint8_t ТИП - может принимать значение STABLE_PH или UNSTABLE_PH.
 - float КИСЛОТНОСТЬ - может принимать значения от 0,001 до 14,000 pH.
 - Возвращаемое значение: bool - результат записи значения (true или false).
 - Примечание:
 - Функция позволяет задать пределы допустимой и высокой флуктуации.
 - Первый параметр позволяет указать тип устанавливаемого предела:
 - STABLE_PH - задать предел допустимой флуктуации.
 - UNSTABLE_PH - задать предел высокой флуктуации.
 - Второй параметр определяет значение устанавливаемого предела.
 - Если среднее значение кислотности за последние 10 секунд не сместилось за предел допустимой флуктуации, то показания кислотности считаются стабильными.
При таких показаниях, функция getStability() возвращает true. - Если среднее значение кислотности за последние 10 секунд сместилось за предел высокой флуктуации, то показания кислотности считаются не стабильными.
При таких показаниях, функция getStability() возвращает false. - Предел допустимой флуктуации должен быть ниже предела высокой флуктуации.
 - Во время калибровки датчик проверяет нормализацию показаний кислотности, значит меняя пределы флуктуаций можно ускорить или замедлить процесс калибровки.
 - Указанные пределы сохраняются в энергонезависимую память.
 - Выполнение функции занимает более 50 миллисекунд.
 - Пример:
 
sensor.setFluctuation(STABLE_PH , 0.002); // Показания будут считаться стабильными, если среднее значение кислотности за последние 10 секунд не смещается более чем на ±0.002 pH. sensor.setFluctuation(UNSTABLE_PH, 0.003); // Показания будут считаться не стабильными, если среднее значение кислотности за последние 10 секунд сместится более чем на ±0.003 pH.
Функция getFluctuation();
- Назначение: Чтение пределов флуктуации кислотности.
 - Синтаксис: getFluctuation( ТИП );
 - Параметр: uint8_t ТИП - может принимать значение STABLE_PH или UNSTABLE_PH.
 - Возвращаемое значение: float - предел флуктуации в pH, или -1 при провале чтения.
 - Примечание:
 - Функция позволяет получить установленные пределы флуктуации кислотности.
 - Параметр позволяет указать тип читаемого предела флуктуаций.
 - STABLE_PH - получить предел допустимой флуктуации.
 - UNSTABLE_PH - получить предел высокой флуктуации.
 - Если среднее значение кислотности за последние 10 секунд не сместилось за предел допустимой флуктуации, то показания кислотности считаются стабильными.
При таких показаниях, функция getStability() возвращает true. - Если среднее значение кислотности за последние 10 секунд сместилось за предел высокой флуктуации, то показания кислотности считаются не стабильными.
При таких показаниях, функция getStability() возвращает false. - По умолчанию, предел допустимой флуктуации кислотности равен 0.002 pH.
 - По умолчанию, предел высокой флуктуации кислотности равен 0.003 pH.
 - Пример:
 
i = sensor.getFluctuation( STABLE_PH ); // Читаем предел допустимой флуктуации кислотности. j = sensor.getFluctuation( UNSTABLE_PH ); // Читаем предел высокой флуктуации кислотности.
Функция setVstp();
- Назначение: Установка чувствительности щупа.
 - Синтаксис: setVstp( НАПРЯЖЕНИЕ );
 - Параметры:
 - float НАПРЯЖЕНИЕ чувствительности в мВ/pH, значение от 0,01 до 655,35.
 - Возвращаемое значение:
 - bool - результат применения нового напряжения (true или false).
 - Примечание:
 - Значение по умолчанию 30,00 мВ (с учётом шунта входным сопротивлением АЦП датчика).
 - Данное значение указывает на сколько изменится напряжение с щупа при изменении водородного показателя жидкости на 1,0 pH.
 - Датчик самостоятельно определяет и сохраняет значение Vstp в процессе калибровки.
 - Чувствительность щупа сохраняется в энергонезависимую память.
 - Выполнение функции занимает более 50 миллисекунд.
 - Пример:
 
sensor.setVstp( 60.0 ); // Указываем датчику новую чувствительность щупа в мВ/pH.
Функция getVstp();
- Назначение: Чтение чувствительности щупа.
 - Синтаксис: getVstp();
 - Параметры: Нет.
 - Возвращаемое значение: float напряжение (0,01...655,35 мВ/pH), или -1 при провале чтения.
 - Пример:
 
i = sensor.getVstp(); // Читаем чувствительность щупа из памяти датчика.
if( i<0 ){ Serial.print("Err"); }else{ Serial.print( (String) "Vstp = "+i+" мВ/pH." ); }
Функция getVin();
- Назначение: Чтение напряжения поданного на вход измерительного щупа.
 - Синтаксис: getVin();
 - Параметры: Нет.
 - Возвращаемое значение: float напряжение (0...6,5535 В), или -1 при провале чтения.
 - Примечание:
 - Напряжение на входе измерительного щупа устанавливается резистивным делителем.
 - Эталонное значение: Vin = 0.5Vcc = 0.5*3.3 = 1.65 В.
 - Функция возвращает не эталонное, а реальное напряжение на входе щупа.
 - Пример:
 
i = sensor.getVin(); // Читаем напряжение на входе щупа.
if( i<0 ){ Serial.print("Err"); }else{ Serial.print( (String) "Vin = "+i+" В." ); }
Функция getVout();
- Назначение: Чтение напряжения на выходе измерительного щупа.
 - Синтаксис: getVout();
 - Параметры: Нет.
 - Возвращаемое значение: float напряжение (0...6,5535 В), или -1 при провале чтения.
 - Примечание: Напряжение на выходе щупа измеряется встроенным АЦП CS1237.
 - Пример:
 
i = sensor.getVout(); // Читаем напряжение на выходе щупа.
if( i<0 ){ Serial.print("Err"); }else{ Serial.print( (String) "Vout = "+i+" В." ); }
Функция setPHn();
- Назначение: Установка нейтральной кислотности для щупа.
 - Синтаксис: setPHn( КИСЛОТНОСТЬ );
 - Параметры:
 - float КИСЛОТНОСТЬ жидкости от 0 до 14 pH при котором напряжение щупа равно 0.
 - Возвращаемое значение:
 - bool - результат применения нового нейтрального pH щупа (true или false).
 - Примечание:
 - Нейтральный водородный показатель жидкости для щупа это pH нулевой точки, такой водородный показатель при котором напряжение щупа равно нулю.
 - При погружении щупа в нейтральную среду (pH=7,0), потенциалы на входе и выходе щупа должны быть одинаковыми (напряжение щупа равно 0) - нулевая точка. Но в процессе старения щупа его нулевая точка смещается, и напряжение щупа будет равно нулю при водородном показателе жидкости отличном от 7,0 pH, это значение и является нейтральным водородным показателем для щупа pHn.
 - Датчик самостоятельно определяет и сохраняет значение pHn в процессе калибровки.
 - Нейтральная кислотность для щупа сохраняется в энергонезависимую память.
 - Выполнение функции занимает более 50 миллисекунд.
 - Пример:
 
sensor.setPHn( 7.02 ); // Указываем датчику новую нейтральную кислотность в pH.
Функция getPHn();
- Назначение: Запрос нейтральной кислотности для щупа.
 - Синтаксис: getPHn();
 - Параметры: Нет.
 - Возвращаемое значение: float кислотность (0...14,000 pH), или -1 при провале чтения.
 - Пример:
 
i = sensor.getPHn(); // Читаем нейтральную кислотность для щупа в pH.
if( i<0 ){ Serial.print("Err"); }else{ Serial.print( (String) "pHn = "+i+" pH." ); }
Обработка ошибок:
Рассмотренные выше функции библиотеки iarduino_MB_pH возвращают не только результат чтения, но и ошибки при записи или чтении. Причину ошибок можно выяснить функцией 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 - Размер полученного ответа превышает размер буфера.
 - Пример:
 
float i = sensor.getPH();            // Читаем кислотность исследуемой жидкости.
if(i>=0){                            // Если значение прочитано без ошибок...
    Serial.print("Кислотность ");    //
    Serial.print( i );               // Выводим прочитанное значение.
    Serial.println(" pH.");          //
}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 - ошибка синтаксиса, означает наличие ошибки в коде, например функция вызвавшая данную ошибку была вызвана с некорректными параметрами, или вызвана до инициализации датчика.
 
Ссылки:
- Датчик кислотности жидкости (pH-метр) RS485 / Modbus с дисплеем.
 - Датчик кислотности жидкости (pH-метр) RS485 / Modbus без дисплея.
 - Trema конвертер UART-RS485.
 - Wiki - Датчик кислотности жидкости (pH-метр) RS485 / Modbus - Datasheet.
 - Wiki - Работа с протоколом Modbus RTU/ASCI по шине RS485.
 - Библиотека iarduino_Modbus.
 - Библиотека iarduino_MB_pH.
 - Wiki - Установка библиотек в Arduino IDE.
 


















Обсуждение