Локальная автономная система сбора данных

На предприятии были закуплены посты мониторинга НЭКСТ-М отечественного производства «Нэкст Технолоджис». Для обеспечения визуализации работы насосных агрегатов,
пожарно- охранной сигнализации, наличия напряжения на пускателях, температуры в помещении, аварийного уровня воды. Сердцем НЭКСТ-М служит ATMEGA 1280 и данный факт обнадёжил в плане возможности создания своего комплекта под конкретные нужды.

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

Работать система должна без зависимости от сотовых сетей, серверов, интернета и разрешительной системы использования радиочастотных ресурсов, не использовать в работе системы контроля и управления компьютеры или максимум периодическое использование ноутбуков, без доступа на объекты в течении длительного времени (6-9 мес.). Конфигурация сети имеет радиальную структуру. Данные собираются в одной точке и далее отправляются для обработки по обычным каналам связи или в виде твердой копии.

Система должна обеспечивать:

  • контроль работы насосных установок
  • технологическую автоматику
  • защиту от последствий аварийных режимов
  • сигнализацию об аварийных режимах
  • подсчет времени наработки
  • подсчет объёма потреблённой электроэнергии
  • контроль температуры оборудования
  • охранно-пожарную сигнализацию
  • периодический дистанционный съём информации
  • неизвестные требования в будущем

Условия работы:

  • территория охвата 1 кв.км.
  • прямая видимость между объектами
  • температура от +50 до -50 С
  • влажность до 100%
  • биологически активные отложения (плесень, сульфатвосстанавливающие бактерии)
  • вибрация, не более, машин 1- 2 классов по ГОСТ ИСО 10816-1-97
  • электромагнитная обстановка- коммутация электродвигателей контакторами КТ 6053, аппаратурой плавного пуска RVS-DN, аппаратурой ПИД- регулирования SIEMENS MICROMASTER, излучения в ISM и GSM диапазоне согласно требованиям к данным устройствам, ручная дуговая сварка на объекте
  • завышенное напряжение сети, кратковременные прекращения электроснабжения, грозовые перенапряжения, перекос фаз при обрыве провода ВЛ в распределительных сетях 6- 10 кВ.

Не смотря на такие жёсткие требования реализация вполне несложная при поэтапном решении задачи.

С учётом всего, в качестве «мозга» задуманного стала плата «Ардуино нано 3.0». Платка от «Robotdyn» имеет контроллер ATMEGA 328, необходимый стабилизатор напряжения 3,3В на
ток 800 мА и конвертер на CH340G UART- USB.

В первую очередь были созданы счётчики наработки как самые актуальные. Ранее применявшиеся промышленные счетчики собранные на PIC-ах с бестрансформаторной схемой питания вышли из строя от бросков напряжения в течении года работы. Остались целыми только подключенные с помощью самодельных блоков питания на напряжение 5В. Для ускорения монтажа и универсальности подключения сигнал о состоянии агрегатов берётся с зажимов коммутационных аппаратов, т.е. регистрация присутствия 1-й фазы напряжения при трёхфазном питании 380В. Для согласования с контроллером применяется промежуточное реле с обмоткой на 220В или оптопара составленная из светодиода и фоторезистора GL5516 или оптопара РС817. Были испытаны в работе все варианты. Светодиод питается выпрямленным напряжением с ограничением тока с помощью двух конденсаторов СВВ22 рассчитаных на напряжение 630В включённых последовательно для сохранности при случайной проверке цепей мегаомметром.
Считывание показаний времени наработки с помощью ЖК экрана ST7735S, передача по радиоканалу данных в режиме реального времени с помощью модуля E01-ML01DP05 на частоте 2,4 МГц. Данное устройство содержит чип nRF24L01+ и усилитель приёма- передачи RFX2401C,
выходная мощность до 100 мВт. Антенны спиральные, рассчитанные на нужный диапазон в онлайн- калькуляторе сайта. Выбор типа антенн обусловлен исключением приёма однократно отраженных волн от окружающих металлоконструкций. Детали антенн распечатаны на 3Д принтере. Текущее состояние счетчиков сохраняется в EEPROM самого контроллера и в случае непредвиденного отключения питания восстанавливается. Временные интервалы для счёта обеспечивает RTC микросхема DS3231 в виде модуля с батареей резервного питания. В БП применены 3 модуля, собственно импульсный источник 220/5В HLK-PM01 600mA, преобразователь из 1-5В в 5В HW-553 и 03962A — контроллер аккумулятора имеющий схему защиты от КЗ, переразряда и перезаряда. Все комплектующие закупались на сайте Aliexpress.

Макетная плата
image alt

Счётчик 4-х канальный. По входам стоят LC фильтры для защиты от помех по линии связи из витой пары. Данные о состоянии объектов контроля постоянно считываются 1 раз в сек., отображаются цветом на ЖК. Обновление показаний и запись в энергонезависимую память происходит каждые 36 сек. 36 сек.- это 1/100 часа, именно в таком формате требуются данные. Каждые 12 сек. происходит передача информации о количестве секунд работы по каждому агрегату контроля. Память EEPROM имеет ограниченное количество циклов записи- стирания, по данным производителя, 100000 раз. Худший вариант- это когда постоянно идет обновление хотя- бы одной ячейки. Объем 1-го счетчика 4 байта, это число формата long, 4 счетчика, итого 16 байт занимает одна запись. Длина памяти микросхемы 1024 байт, после 64-х записей 4-х счетчиков запись начнётся сначала. В библиотеке EEPROM метод EEPROM.put не производит запись, если значение ячейки и записываемой информации совпадает, деградации ячеек не будет. В итоге время гарантированной наработки памяти будет более 7 лет. Время возможной, но негарантированной работы может быть намного больше.

Принципильная схема
image alt

Программа в Arduino IDE
//12 328 байт (38%)

#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#include <EEPROM.h>
#include <Wire.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(9, 10); // объект radio для работы с библиотекой RF24,
// и номера выводов nRF24L01+ (CE, CSN)
#include <DS3231.h>
DS3231 rtc(SDA, SCL);
Time t;

//#define TFT_CS 10
#define TFT_CS 8
#define TFT_RST -1 // you can also connect this to the Arduino reset
// in which case, set this #define pin to -1!
//#define TFT_DC 9 // DC=RS=A0- варианты обозначений вывода выбора регистра команд или данных.
#define TFT_DC 3

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

// Option 2: use any pins but a little slower!
#define TFT_SCLK 13 // set these to be whatever pins you like!
#define TFT_MOSI 11 // set these to be whatever pins you like!
//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
#include <avr/wdt.h>

byte shift = 52;
byte pinState;
unsigned long pump[4];// массив с 4 значениями счётчиков секунд
float m = 3600.0;
unsigned int address = 0;
int rc;// переменная для счетчиков
unsigned long sumprim = 0;
unsigned long sumsec = 0;
byte i = 0;
byte k = 34;
unsigned int z = 0;
byte b = B00000001;
byte pumrcounter [4]; // массив для хранения состояний объектов, 1- откл., 0- вкл.
int start = 0; //

void setup() {

rtc.begin();
radio.begin(); // Инициируем работу nRF24L01+
radio.setChannel(120); // канал передачи данных (от 0 до 127).
radio.setDataRate (RF24_250KBPS); // скорость передачи данных (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS).
radio.setPALevel (RF24_PA_MAX); // мощность передатчика (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm,
// RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm)
radio.openWritingPipe (0xAABBCCDD11LL); // Открываем трубу с идентификатором для передачи данных

// Для установки времени- раскомментировать нужные строки
//rtc.setDOW(1); // День недели
//rtc.setTime(21, 20, 0); // Время, в формате 24 часа.
//rtc.setDate(29, 10, 2018); // Дата, 29 октября 2018г.

tft.initR(INITR_BLACKTAB); // initialize a ST7735S chip, black tab
// Use this initializer (uncomment) if you're using a 1.44" TFT
//tft.initR(INITR_144GREENTAB); // initialize a ST7735S chip, RED rcB tab
tft.setTextWrap(false); // Allow text to run off right edge
tft.setRotation( 2 ); // for BLACK PCB and RED tft.setRotation(0) or not.
tft.fillScreen(ST7735_BLACK); // очистка экрана

DDRD = DDRD | B00000000;
PORTD = PORTD | B11110000;// программная подтяжка работает, высокий уровень-
// контролируемые объекты «не работают», во все 4 старших порта D записана «1», не идет счет.

for ( rc = 0; rc < 4; rc++)
{
tft.setCursor ( 3, rc * 10 + shift ); // вывод номеров позиций объектов контроля
tft.print ( rc + 1 );
}

tft.setCursor (12, 0); // вывод 3-х строчек текста
tft.println («DEVELOPERS & BUILD» ); // для восхваления себя любимых
tft.setCursor (24, 10); // или злобного копирайта
tft.print («DEVELOPER M.M.»);
tft.setCursor (28, 20);
tft.print («BUILD-ER D.D.»);

//восстановление данных/////////////////////////////////////////////////////////

for ( z = 0; z < 1023; z += 16 ) { // Перебирает все ячейки еепрома
//и записывает в массив из 4-х переменных pump, по 4 байта каждый счетчик, т.к.
// переменная беззнаковая лонг. Счетчиков 4, одна запись всех 4-х занимает 16 байт.
EEPROM.get ( z, pump [0]); // так, без цикла for, меньше объём
EEPROM.get ( z + 4, pump [1]);
EEPROM.get ( z + 8, pump [2]);
EEPROM.get ( z + 12, pump [3]);

// присвоение нового очередного значения суммы 4-x счётчиков
sumprim = (pump [0] + pump [1] + pump [2] + pump [3]);

// сравнивается новое значение суммы 4-х счетчиков в переменной sumprim с предыдущим значением в переменной
// sumsec и если предыдущая сумма меньше или равна новой сумме, присваивается новое большее или равное
// sumsec значение.

if ( sumsec <= sumprim ) {
sumsec = sumprim; //

//и присваивается переменной address текущее значение z, z- это адрес начала блока в 16 байт из 4-х значений
// счетчиков, записанных в одно и то-же время ( т.к. при опросе порта записываются одновременно все его 8 бит,
// в том числе наши нужные старшие 4 бита порта D).
address = z;
}
}

// еще раз обращение к памяти еепром по адресу начала блока в 16 байт из 4-х значений счетчиков записанных
// последними, т.е. значения перед выключением или перезагрузкой по причине зависания. Запись последних
// значений счетчиков в массив из 4-х переменных pump.

EEPROM.get ( address, pump [0]);
EEPROM.get ( address + 4, pump [1]);
EEPROM.get ( address + 8, pump [2]);
EEPROM.get ( address + 12, pump [3]);

address += 16; // увеличения адреса для записи следующего блока не затирая данные последней записи

// конец восстановления данных////////////////////////////////////////////////////////////////

attachInterrupt(0, count, RISING); // pin D2, разрешение работы прерывания, каждую секунду приходят
// импульсы от RTC DS3231 с выхода SQW

wdt_enable (WDTO_8S); // запуск сторожевого таймера, перезагружает контроллер в случае зависания, время,
// за которое надо подать команду сброса таймера wdt_reset( и избежать перезагрузки при нормальной работе- 8 сек.
// для тестов не рекомендуется устанавливать значение менее 8 сек.В данном случае сброс таймера происходит в пре-
// рывании, а оно каждую секунду.

}

void loop() {
// пустой цикл, здесь будет контроль за неполнофазным режимом работы эл.двигателя
}

void count() {

tft.setTextColor(ST7735_WHITE); // установка цвета шрифта
t = rtc.getTime(); // считывание времени
tft.setCursor ( 5, 120 ); // установка позиции курсора
tft.fillRect ( 5, 120, 50, 7, ST7735_BLACK); // очистка области вывода времени
tft.print(rtc.getTimeStr()); // вывод показаний часов

wdt_reset(); // сброс сторожевого таймера каждый цикл, т.е.секунду

for (rc = 0; rc < 4; rc ++) // начало цикла проверки соответствия состояния входных
// битов порта предыдущему считанному состоянию битов порта D
{
pinState = (PIND >> 4) & ( b << rc );

if (pumrcounter [rc] != pinState) { // и если не соответствует, то
pumrcounter [rc] = pinState; // присвоение переменной состояния бита порта нового значения 1/0
}
// индикация состояния объектов контроля цветом
// BLUE- это небольшой глюк имеющегося экрана ( или библиотеки? ), перепутаны RGB и BGR.
if (pinState == ( b << rc )) {
tft.fillRect(15, ((rc * 10 + shift)), 7, 7, ST7735_BLUE); // для счета по низкому уровню поменять GREEN на BLUE
} else {
tft.fillRect(15, ((rc * 10 + shift)), 7, 7, ST7735_GREEN); // для счета по низкому уровню поменять BLUE на GREEN
pump [rc] += 1; // добавляем в счетчик времени работы 1 секунду
}
}

k ++;
if ( k == 36 ) {
k = 0;

tft.fillRect ( 30, shift, 97, 40, ST7735_BLACK ); // очистка области вывода времени наработки
tft.fillRect ( 60, 120, 73, 7, ST7735_BLACK); // и даты

tft.setCursor ( 60, 120 ); // установка позиции курсора
tft.print(rtc.getDateStr()); // вывод даты на экран LCD

for (rc = 0; rc < 4; rc ++) //вывод показаний наработки в целых, десятых и
{
tft.setCursor ( 30, rc * 10 + shift );// сотых долях часа со сдвигом на экране вниз на 10 пикселей
tft.println(pump [rc] / m);
}

// запись «сырых» значений наработки (в секундах)в EEPROM //////////////////////////////

for (rc = 0; rc < 4; rc ++)
{
EEPROM.put(address, pump [rc]);
address += sizeof(float); // инкремент переменной адреса записи
}
}

// отправляем данные по радиоканалу из data указывая сколько байт надо отправить.
if ((k == 6 ) || (k == 18 ) || (k == 30 )) {

unsigned long data;

radio.write(&start, sizeof(start));

for ( i = 0; i < 4; i ++) {
data = pump [i ];
radio.write( &data, sizeof( data));
}
}
}

Небольшие замечания в конце. Счёт идет при низком логическом уровне на входах.

Сопротивления подтяжки R2-R5 36 кОм для варианта с фоторезисторами GL5516. В случае фототранзисторной оптопары и реле, поставить 4,7- 5,1 кОм. Загрузчик Arduino Nano v3.0 заменён на Arduino Uno с помощью программатора TL866A для корректной работы сторожевого таймера. Фьюзы поправлены для работы при напряжении выше 4,3 В. Внешняя цепь сброса R6 C3 не использовалась. В примере программы частота передатчика не соответствует нелицензируемому диапазону, диапазон 2,4 МГц ограничен частотами 2400.0—2483.5 МГц.

Диапазон передатчика E01-ML01DP05 составляет 2400- 2525 МГц. Ширина полосы одного канала- 1 МГц, при настройке скорости как «RF24_2MBPS» будет занят указанный radio.setChannel(120) канал и следующий, т.е. полоса будет 2 МГц.
Поделиться публикацией

Комментарии 3

    +2
    Я надеюсь ЭТО было сделано бесплатно?
      +1
      Я бы поставил ЭТО куда-то, только если бы мне заплатили. Так, чтобы хватило на взрывозащищённый шкафчик для оборудования, как минимум. Страх божий.
        +1
        От осколков конденсаторов шкафчик, конечно, поможет, а вот от 217 УК РФ — уже вряд ли.

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

    Самое читаемое