Système autonome local de collecte de données

L'entreprise a acquéré des postes de surveillance NEXXT-M de production nationale de « Nextr Technologies ». Pour visualiser le fonctionnement des groupes de pompes,
la détection d'incendie et d'intrusion, la présence de tension sur les contacteurs, la température ambiante, le niveau d'eau d'urgence. Le cœur du NEXXT-M est un ATMEGA 1280, ce qui a encouragé la création d'un ensemble spécifique aux besoins particuliers.

L'objectif était de créer dans des délais très courts et avec un minimum de coûts un système totalement autonome de supervision locale adapté à des besoins spécifiques. La base est un microcontrôleur. Le développement et la fabrication sont réalisés par le personnel lui-même.

Le système doit fonctionner sans dépendance des réseaux cellulaires, serveurs, d'internet et de systèmes d'autorisation pour l'utilisation des ressources radio, sans utiliser d'ordinateurs dans le contrôle et la gestion, ou au maximum une utilisation ponctuelle de portables, sans accès sur les sites pendant une longue période (6-9 mois). La configuration du réseau a une structure radiale. Les données sont collectées à un point et ensuite envoyées pour traitement par des canaux de communication ordinaires ou sous forme de copie physique.

Le système doit assurer :

  • le contrôle du fonctionnement des installations de pompage
  • l'automatisation technologique
  • la protection contre les conséquences des modes d'urgence
  • la signalisation des modes d'urgence
  • le calcul du temps de fonctionnement
  • le calcul de la consommation d'électricité
  • le contrôle de la température de l'équipement
  • la détection d'incendie et d'intrusion
  • la collecte d'informations à distance de manière périodique
  • des exigences inconnues à l'avenir

Conditions de travail :

  • territoire de couverture de 1 km².
  • visibilité directe entre les objets
  • température de +50 à -50 °C
  • humidité jusqu'à 100 %
  • dépôts biologiquement actifs (moisissure, bactéries réductrices de sulfate)
  • vibration, pas plus que des machines de classes 1-2 selon la norme ISO GOST 10816-1-97
  • environnement électromagnétique - commutation des moteurs électriques par contacteurs KT 6053, équipements de démarrage progressif RVS-DN, équipements de régulation PID SIEMENS MICROMASTER, émissions dans les bandes ISM et GSM conformément aux exigences de ces dispositifs, soudure à l'arc manuelle sur site.
  • tension réseau excessive, interruptions temporaires de l'approvisionnement électrique, surtensions dues aux orages, déséquilibre de phases lors de la rupture de fils de lignes aériennes dans les réseaux de distribution 6-10 kV.

Malgré ces exigences strictes, la mise en œuvre est tout à fait simple lorsqu'on aborde le problème par étapes.

En tenant compte de tout cela, la carte « Arduino Nano 3.0 » a été choisie comme le « cerveau » du projet. La carte de « Robotdyn » est équipée d'un contrôleur ATMEGA 328, ainsi que d'un stabilisateur de tension de 3,3 V.
un courant de 800 mA et d'un convertisseur sur CH340G UART-USB.

Dans un premier temps, des compteurs de fonctionnement ont été créés comme les plus pertinents. Des compteurs industriels précédemment utilisés, construits sur des PIC avec un schéma d'alimentation sans transformateur, sont tombés en panne à cause des fluctuations de tension durant l’année de fonctionnement. Seuls ceux connectés par des blocs d'alimentation fabriqués maison de 5 V sont restés intacts. Pour accélérer l'installation et assurer une connectivité universelle, le signal sur l'état des unités est prélevé sur les bornes des dispositifs de commutation, c'est-à-dire l'enregistrement de la présence de la 1ère phase de tension lors de l'alimentation triphasée de 380 V. Pour l'adaptation au contrôleur, un relais intermédiaire avec enroulement à 220 V ou un optocoupleur composé d'une LED et d'une photorésistance GL5516 ou un optocoupleur PC817 est utilisé. Toutes les variantes ont été testées. La LED est alimentée par une tension redressée avec une limitation de courant à l'aide de deux condensateurs SVV22 conçus pour une tension de 630 V, connectés en série pour la protection lors d'un test accidentel des circuits avec un mégohmmètre.
La lecture des heures de fonctionnement se fait à l'aide d'un écran LCD ST7735S, et les données sont transmises en temps réel par radio grâce au module E01-ML01DP05 fonctionnant à une fréquence de 2,4 MHz. Cet appareil contient une puce nRF24L01+ et un amplificateur de réception-transmission RFX2401C,
avec une puissance de sortie allant jusqu'à 100 mW. Les antennes sont hélicoïdales, conçues pour la plage spécifiée dans un calculateur en ligne. siteLe choix du type d'antennes est déterminé par l'exclusion de la réception des ondes réfléchies à partir des structures métalliques environnantes. Les pièces des antennes sont imprimées sur une imprimante 3D. L'état actuel des compteurs est enregistré dans l'EEPROM du contrôleur lui-même et, en cas de coupure de courant imprévue, il est restauré. Les intervalles de temps pour le comptage sont assurés par le circuit RTC DS3231 sous forme de module avec une batterie de secours. Dans l'alimentation électrique, trois modules sont utilisés : une source d'impulsions, à savoir une entrée de 220/5V HLK-PM01 600mA, un convertisseur de 1-5V à 5V. HW-553 et 03962A — contrôleur de batterie doté d'un schéma de protection contre les courts-circuits, la décharge excessive et la surcharge. Tous les composants ont été achetés sur le site Aliexpress.

Plaque de prototypeSystème autonome local de collecte de données
Compteur à 4 canaux. Des filtres LC sont installés sur les entrées pour protéger contre les interférences sur la ligne de communication à paires torsadées. Les données sur l'état des objets de contrôle sont constamment lues une fois par seconde et affichées par couleur sur un écran LCD. La mise à jour des lectures et l'enregistrement dans la mémoire non volatile ont lieu toutes les 36 secondes. 36 secondes – c'est 1/100 d'heure, c'est justement dans ce format que les données sont nécessaires. Toutes les 12 secondes, des informations sur le nombre de secondes de fonctionnement pour chaque appareil de contrôle sont transmises. La mémoire EEPROM a un nombre limité de cycles d'écriture et d'effacement, selon le fabricant, 100000 fois. Le pire des cas est lorsque la mise à jour d'au moins une cellule se fait en continu. La taille d'un compteur est de 4 octets, c'est un nombre au format long, donc 4 compteurs occupent 16 octets pour une seule écriture. La longueur de la mémoire de la puce est de 1024 octets, après 64 écritures des 4 compteurs, l'écriture recommencera. Dans la bibliothèque EEPROM, la méthode EEPROM.put n'effectue pas d'écriture si la valeur de la cellule et des informations à écrire coïncident, il n'y aura pas de dégradation des cellules. En fin de compte, le temps d'utilisation garanti de la mémoire sera supérieur à 7 ans. Le temps d'utilisation possible, mais non garanti, peut être beaucoup plus long.

Schéma principalSystème autonome local de collecte de données
Programme dans l'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); // objet radio pour travailler avec la bibliothèque 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]; // tableau avec 4 valeurs de compteurs de secondes
float m = 3600.0;
unsigned int address = 0;
int rc; // variable pour les compteurs
unsigned long sumprim = 0;
unsigned long sumsec = 0;
byte i = 0;
byte k = 34;
unsigned int z = 0;
byte b = B00000001;
byte pumrcounter[4]; // tableau pour stocker les états des objets, 1 - éteint, 0 - allumé.
int start = 0; //

void setup() {

rtc.begin();
radio.begin(); // Nous démarrons le fonctionnement du nRF24L01+
radio.setChannel(120); // canal de transmission de données (de 0 à 127).
radio.setDataRate (RF24_250KBPS); // vitesse de transmission des données (RF24_250KBPS, RF24_1MBPS, RF24_2MBPS).
radio.setPALevel (RF24_PA_MAX); // puissance de l'émetteur (RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm,
// RF24_PA_HIGH=-6dBm, RF24_PA_MAX=0dBm)
radio.openWritingPipe (0xAABBCCDD11LL); // Ouverture d'un tube avec l'identifiant pour la transmission de données

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

tft.initR(INITR_BLACKTAB); // initialiser une puce ST7735S, onglet noir
// 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); // Permet au texte de déborder sur le bord droit
tft.setRotation( 2 ); // pour PCB NOIR et RED tft.setRotation(0) ou pas.
tft.fillScreen(ST7735_BLACK); // effacement de l'écran

DDRD = DDRD | B00000000;
PORTD = PORTD | B11110000; // la résistance de tirage fonctionne, niveau élevé-
// контролируемые объекты «не работают», во все 4 старших порта D записана «1», не идет счет.

for ( rc = 0; rc < 4; rc++)
{
tft.setCursor ( 3, rc * 10 + shift ); // affichage des numéros de positions des objets de contrôle
tft.print ( rc + 1 );
}

tft.setCursor (12, 0); // affichage de 3 lignes de texte
tft.println («DÉVELOPPEURS & CONSTRUCTION» ); // pour faire l'éloge de nous-mêmes
tft.setCursor (24, 10); // ou d'un copyright malveillant
tft.print («DÉVELOPPEUR M.M.»);
tft.setCursor (28, 20);
tft.print («CONSTRUCTEUR D.D.»);

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

for ( z = 0; z < 1023; z += 16 ) { // Parcourt toutes les cellules de l'EEPROM
//и записывает в массив из 4-х переменных pump, по 4 байта каждый счетчик, т.к.
// переменная беззнаковая лонг. Счетчиков 4, одна запись всех 4-х занимает 16 байт.
EEPROM.get ( z, pump [0]); // donc, sans boucle for, moins de volume
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; // augmentation de l'adresse pour enregistrer le prochain bloc sans écraser les données de la dernière entrée

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

attachInterrupt(0, count, RISING); // broche D2, permission de travail de l'interruption, chaque seconde arrivent
// импульсы от RTC DS3231 с выхода SQW

wdt_enable (WDTO_8S); // démarrage du temporisateur de surveillance, redémarre le contrôleur en cas de blocage, temps,
// за которое надо подать команду сброса таймера wdt_reset( и избежать перезагрузки при нормальной работе- 8 сек.
// для тестов не рекомендуется устанавливать значение менее 8 сек.В данном случае сброс таймера происходит в пре-
// рывании, а оно каждую секунду.

}

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

void count() {

tft.setTextColor(ST7735_WHITE); // réglage de la couleur de la police
t = rtc.getTime(); // lecture du temps
tft.setCursor ( 5, 120 ); // réglage de la position du curseur
tft.fillRect ( 5, 120, 50, 7, ST7735_BLACK); // effacement de la zone d'affichage du temps
tft.print(rtc.getTimeStr()); // affichage des horaires

wdt_reset(); // réinitialisation du temporisateur de surveillance chaque cycle, c'est-à-dire chaque seconde

for (rc = 0; rc < 4; rc ++) // début de la boucle de vérification de la correspondance de l'état des entrées
// битов порта предыдущему считанному состоянию битов порта D
{
pinState = (PIND >> 4) & ( b << rc );

if (pumrcounter [rc] != pinState) { // et si ce n'est pas conforme, alors
pumrcounter [rc] = pinState; // assignation à la variable de l'état du bit de port, nouvelle valeur 1/0
}
// индикация состояния объектов контроля цветом
// BLUE- это небольшой глюк имеющегося экрана ( или библиотеки? ), перепутаны RGB и BGR.
if (pinState == ( b << rc )) {
tft.fillRect(15, ((rc * 10 + shift)), 7, 7, ST7735_BLUE); // pour le comptage au niveau bas changer GREEN en BLUE
} else {
tft.fillRect(15, ((rc * 10 + shift)), 7, 7, ST7735_GREEN); // pour le comptage au niveau bas changer BLUE en GREEN
pump [rc] += 1; // ajout au compteur de temps de fonctionnement de 1 seconde
}
}

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

tft.fillRect ( 30, shift, 97, 40, ST7735_BLACK ); // effacement de la zone d'affichage du temps de fonctionnement
tft.fillRect ( 60, 120, 73, 7, ST7735_BLACK); // et la date

tft.setCursor ( 60, 120 ); // positionnement du curseur
tft.print(rtc.getDateStr()); // affichage de la date sur l'écran LCD

for (rc = 0; rc < 4; rc++) // affichage des lectures en entiers, dixièmes et
{
tft.setCursor ( 30, rc * 10 + shift ); // centièmes d'heure avec un décalage de 10 pixels vers le bas
tft.println(pump [rc] / m);
}

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

for (rc = 0; rc < 4; rc++)
{
EEPROM.put(address, pump [rc]);
address += sizeof(float); // incrément de la variable d'adresse d'écriture
}
}

// отправляем данные по радиоканалу из 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));
}
}
}

Quelques remarques à la fin. Le comptage commence lors d'un niveau logique bas aux entrées.

Les résistances de tirage R2-R5 sont de 36 kΩ pour l'option avec les photorésistances GL5516. Dans le cas d'un optocoupleur phototransistor et d'un relais, une valeur de 4,7-5,1 kΩ doit être utilisée. Le chargeur Arduino Nano v3.0 a été remplacé par un Arduino Uno à l'aide du programmateur TL866A pour un fonctionnement correct du minuteur de surveillance. Les fusibles ont été modifiés pour fonctionner à des tensions supérieures à 4,3 V. Le circuit de réinitialisation externe R6 C3 n'a pas été utilisé. Dans l'exemple de programme, la fréquence du transmetteur ne correspond pas à la bande non licenciée, la bande de 2,4 MHz est limitée aux fréquences 2400.0—2483.5 MHz.

La bande du transmetteur E01-ML01DP05 est de 2400-2525 MHz. La largeur de bande d'un canal est de 1 MHz, et lorsque la vitesse est réglée sur «RF24_2MBPS», le canal radio.setChannel(120) spécifié et le suivant seront occupés, c'est-à-dire que la bande sera de 2 MHz.

Source : habr.com

Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS 🔥 Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster