本地自治数据采集系统

本文的续篇
该公司购买了国产NEXT Technologies的NEXT-M监控站。 为确保抽油机操作的可视化,
火灾警报,启动器电压,室温,紧急水位。 NEXT-M的核心是ATMEGA 1280,就为特定需求创建自己的套件的可能性而言,这一事实令人鼓舞。

该任务旨在在最短的时间内以最低的成本创建一个完全自主的本地调度系统。 基础是微控制器。 开发,制造,全部由员工自己承担。

该系统应在不依赖蜂窝网络,服务器,互联网和使用射频资源的许可系统的情况下工作,并且在长时间(6-9个月)内不能访问对象的情况下,不要使用计算机或在监控系统中最大限度地定期使用便携式计算机。 网络配置具有放射状结构。 一次收集数据,然后通过常规通信通道或以纸质形式发送以进行处理。

系统应提供:

  • 监控抽油机的运行
  • 技术自动化
  • 紧急防护
  • 紧急警报
  • 营业时间
  • 计算用电量
  • 设备温度控制
  • 火警
  • 定期远程阅读信息
  • 未来需求未知

工作条件:

  • 覆盖面积1平方公里。
  • 对象之间的直接可见性
  • 温度从+50到-50 C
  • 湿度高达100%
  • 具有生物活性的沉积物(霉菌,硫酸盐还原菌)
  • 振动,仅此而已,符合GOST ISO 10816-1-97的1-2类机器
  • 电磁环境-通过KT 6053接触器,RVS-DN软起动器,SIEMENS MICROMASTER PID控制设备,根据这些设备的要求在ISM和GSM范围内辐射,现场手工电弧焊来切换电动机
  • 在6-10 kV配电网络中架空线路开路的情况下,网络过压,短期停电,雷电过电压,相位不平衡。

尽管有如此严格的要求,但通过分阶段解决该问题的实现仍然非常简单。

考虑到所有这些,Arduino Nano 3.0开发板成为了构思的“大脑”。 Robotdyn披肩具有ATMEGA 328控制器,必要的3.3V稳压器
800 mA电流和转换器至CH340G UART-USB。

首先,创建最相关的运行时间计数器。 在运行年份中,以前在PIC上收集的带有无变压器电源电路的工业电表由于电涌而发生故障。 仅在使用5V的家用电源的情况下完好无损。 为了加快安装速度和连接的通用性,从开关设备的端子,即开关设备的端子上获取有关设备状态的信号。 用三相电源380V记录第一相电压的存在。 为了与控制器配合,使用具有220V绕组的中间继电器或由LED和光敏电阻GL5516组成的光耦合器或光耦合器PC817。 所有选项均经过测试。 该LED由一个整流电流供电,该整流电压使用两个专为630V设计的CBB22电容器来限制电流,并在用兆欧表对电路进行随机检查时串联以确保安全。
使用ST7735S液晶显示屏读取运行时间,并使用E01-ML01DP05模块以2.4 MHz的频率通过空中传输实时数据。 该器件包含一个nRF24L01 +芯片和一个RFX2401C收发放大器,
输出功率高达100 mW。 在站点的在线计算器中为所需范围设计的螺旋天线。 天线类型的选择是由于排除了来自周围金属结构的一次反射波的接收。 天线零件在3D打印机上打印。 计数器的当前状态存储在控制器本身的EEPROM中,并在意外断电时恢复。 RTC DS3231芯片以带有备用电池的模块的形式提供了计数时间间隔。 电源模块中使用了三个模块,HLK-PM01 600mA 220 / 5V脉冲源本身, 1-5W至5V的HW-55303962A转换器是电池控制器, 具有短路,过放电和过充电保护电路。 所有组件均在Aliexpress网站上购买。

面包板
图片替代

4通道计数器。 LC滤波器位于输入端,可防止双绞线通信线路受到干扰。 每秒不断读取有关控制对象状态的数据1次,并在LCD上以彩色显示。 每隔36秒更新一次读数并将其记录在非易失性存储器中。 36秒是1/100小时,这种格式的数据是必需的。 每12秒 有关每个控制单元的操作秒数信息被传送。 根据制造商的说法,EEPROM存储器具有有限的写-擦除循环次数,为100,000次。 最差的选择是至少一个单元不断更新。 第一个计数器的大小是4个字节,这是一个长格式数字,4个计数器,总共16个字节占用一条记录。 芯片存储器长度为1024字节,在4个计数器的64个条目输入之后,将再次开始记录。 在EEPROM库中,EEPROM.put方法不记录,如果单元的值与写入的信息匹配,则不会降低单元的性能。 结果,存储器的保证工作时间将超过7年。 可能但无用的工作时间可能会更长。

电路图
图片替代

Arduino IDE中的程序
// 12328字节(38%)

#include <Adafruit_GFX.h> //核心图形库
#include <Adafruit_ST7735.h> //特定于硬件的库
#include <SPI.h>
#include <EEPROM.h>
#include <Wire.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24收音机(9,10); //使用RF24库的无线电对象,
//和引脚号nRF24L01 +(CE,CSN)
#include <DS3231.h>
DS3231 rtc(SDA,SCL);
时间t;

//#define TFT_CS 10
#定义TFT_CS 8
#define TFT_RST -1 //您也可以将其连接到Arduino重置
//在这种情况下,请将此#define引脚设置为-1!
//#define TFT_DC 9 // DC = RS = A0-选项,用于指定命令或数据寄存器选择的输出。
#定义TFT_DC 3

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

//选项2:使用任何引脚,但速度要慢一些!
#define TFT_SCLK 13 //将它们设置为您喜欢的任何引脚!
#define TFT_MOSI 11 //将它们设置为您喜欢的任何引脚!
// Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,TFT_DC,TFT_MOSI,TFT_SCLK,TFT_RST);
#include <avr / wdt.h>

字节移位= 52;
字节pinState;
无符号长泵[4]; //计数为4秒的数组
浮点数m = 3600.0;
无符号整数地址= 0;
int rc; //计数器变量
无符号长sumprim = 0;
无符号长和= 0;
字节i = 0;
字节k = 34;
无符号整数z = 0;
字节b = B00000001;
字节pumrcounter [4]; //用于存储对象状态的数组,1-关闭,0-打开
int start = 0; //

无效设置(){

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); //日期,2018年10月29日

tft.initR(INITR_BLACKTAB); //初始化ST7735S芯片,黑色标签
//如果您使用的是1.44“ TFT,请使用此初始化程序(取消注释)
//tft.initR(INITR_144GREENTAB); //初始化ST7735S芯片,RED rcB选项卡
tft.setTextWrap(false); //允许文字从右边缘开始
tft.setRotation(2); //是否为BLACK PCB和RED tft.setRotation(0)。
tft.fillScreen(ST7735_BLACK); //清除屏幕

DDRD = DDRD | B00000000;
PORTD = PORTD | B11110000; //软件收紧工作,高级-
//被监视的对象“不起作用”,“ 1”被写入D的所有4个高级端口,该帐户不存在。

对于(rc = 0; rc <4; rc ++)
{
tft.setCursor(3,rc * 10 +移位); //显示控制对象的位置数
tft.print(rc + 1);
}

tft.setCursor(12,0); //输出3行文字
tft.println(“开发人员和制造商”); //赞美你的亲人
tft.setCursor(24,10); //或邪恶的版权
tft.print(“ DEVELOPER MM”);
tft.setCursor(28,20);
tft.print(“ BUILD-ER DD”);

//数据恢复/////////////////////////////////////////////// ///////////

for(z = 0; z <1023; z + = 16){//遍历其行业的所有单元
//并写入4个变量Pump的数组,每个计数器4个字节,因为
//变量unsigned long。 计数器4,所有4中的一条记录占用16个字节。
EEPROM.get(z,泵[0]); //因此,没有for循环,体积较小
EEPROM.get(z + 4,泵[1]);
EEPROM.get(z + 8,泵[2]);
EEPROM.get(z + 12,泵[3]);

//分配4-x计数器总和的新下一个值
sumprim =(泵[0] +泵[1] +泵[2] +泵[3]);

//比较变量sumprim中4个计数器的和的新值与变量中的前一个值
// sumsec,如果先前的金额小于或等于新的总和,则会分配一个新的大于或等于
// sumsec值。

如果(sumsec <= sumprim){
sumsec = sumprim; //

//,并将当前值z分配给address变量,z是从4个值开始的16个字节的块开头的地址
//同时记录计数器(因为轮询端口时,其所有8位都同时记录
//包括我们想要的端口D的高4位)。
地址= z;
}
}

//再一次,从记录的4个计数器值开始,在块的起始地址访问epromprom存储器为16个字节
//最后,即 因挂起而关闭或重新启动之前的值。 记录最后
//包含4个变量泵数组的计数器的值。

EEPROM.get(地址,泵[0]);
EEPROM.get(地址+ 4,泵[1]);
EEPROM.get(地址+ 8,泵[2]);
EEPROM.get(地址+ 12,泵[3]);

地址+ = 16; //增加用于写入下一个块的地址,而不会覆盖最后一条记录的数据

//数据恢复结束////////////////////////////////////////////// ///////////////////

attachInterrupt(0,count,RISING); //引脚D2,启用中断操作,每秒钟到达
//来自SQW输出的RTC DS3231的脉冲

wdt_enable(WDTO_8S); //启动看门狗计时器,在挂起,时间,
//您需要为其发送wdt_reset timer reset命令(并避免在正常操作期间重启-8秒)。
//对于测试,建议不要将该值设置为少于8秒,在这种情况下,计时器会在
//进行挖掘,然后每秒进行一次挖掘。

}

无效循环(){
//空循环,此处将控制电动机的异相运行模式
}

无效计数(){

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混合在一起。
如果(pinState ==(b << rc)){
tft.fillRect(15,(((rc * 10 + shift)),7,7,ST7735_BLUE); //对于低级帐户,请将GREEN更改为BLUE
}其他{
tft.fillRect(15,(((rc * 10 + shift)),7,7,ST7735_GREEN); //对于低级别帐户,请将BLUE更改为GREEN
泵[rc] + = 1; //将1秒添加到运行时计数器
}
}

k ++;
如果(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()); //在液晶屏上显示日期

for(rc = 0; rc <4; rc ++)//以整数,十分之一和十进制输出操作时间读数
{
tft.setCursor(30,rc * 10 + shift); //百分之一小时在屏幕上向下移动10个像素
tft.println(pump [rc] / m);
}

//在EEPROM中记录“原始”工作时间值(以秒为单位)/////////////////////////////

对于(rc = 0; rc <4; rc ++)
{
EEPROM.put(地址,泵[rc]);
地址+ = sizeof(float); //增加记录地址变量
}
}

//通过指示要发送多少字节的数据通过空中发送数据。
如果((k == 6)||(k == 18)||(k == 30)){

无符号长数据;

radio.write(&开始,sizeof(开始));

对于(i = 0; i <4; i ++){
数据=泵[i];
radio.write(&数据,sizeof(数据));
}
}
}

最后一些评论。 该帐户在输入时处于低逻辑级别。
悬架电阻R2-R5 36 kOhm(适用于GL5516光敏电阻的版本)。 对于光电晶体管光电耦合器和继电器,请提供4.7-5.1 kOhm。 使用TL866A编程器将Arduino Nano v3.0引导程序替换为Arduino Uno,以实现正确的看门狗操作。 已对保险丝进行了校正,使其能够在4.3 V以上的电压下工作。未使用外部复位电路R6 C3。 在示例程序中,发射器频率不符合非许可范围,2.4 MHz范围限于频率2400.0-2483.5 MHz。
E01-ML01DP05的发射器范围是2400-2525 MHz。 将速度设置为“ RF24_2MBPS”时,一个指定的radio.setChannel(120)频道的一个频道的带宽为1 MHz,下一个频道即被占用 该频段将为2 MHz。
延续性

Source: https://habr.com/ru/post/zh-CN447168/


All Articles