本地自主数据采集系统

该公司购买了Next Technologies 国产的NEKST-M 监控桩。为了确保抽油机运行的可视化,
火灾和安全警报、启动器电压、室温、紧急水位。 NEKST-M 的核心是 ATMEGA 1280,这一事实令人鼓舞,因为您可以根据特定需求创建自己的套件。

任务是在最短的时间内以最低的成本创建一个完全自主的本地调度系统,以满足特定需求。其基础是微控制器。由员工自己开发、制造、创造。

该系统必须在不依赖蜂窝网络、服务器、互联网和射频资源使用许可系统的情况下运行,在监测和控制系统的运行中不得使用计算机,或者最多定期使用笔记本电脑,而无需访问长期对象(6-9 个月)。网络配置具有放射状结构。数据在某一点收集,然后通过常规通信渠道或作为硬拷贝发送进行处理。

系统必须提供:

  • 监控抽油机的运行
  • 技术自动化
  • 免受紧急情况后果的影响
  • 紧急信号
  • 运行时间计算
  • 计算消耗的电量
  • 设备温度控制
  • 安全和火灾报警
  • 定期远程记录信息
  • 未来需求未知

工作条件:

  • 覆盖面积1平方公里。
  • 物体之间的直接可见性
  • 温度从+50℃到-50℃
  • 湿度高达 100%
  • 生物活性沉积物(霉菌、硫酸盐还原菌)
  • 根据 GOST ISO 1-2-10816,1-97 级机器的振动,仅此而已
  • 电磁环境 - 使用 KT 6053 接触器切换电动机、RVS-DN 软启动设备、SIEMENS MICROMASTER PID 控制设备、根据这些设备的要求在 ISM 和 GSM 范围内的辐射、现场手工电弧焊
  • 6-10kV配电网中电网电压过高、供电短时中断、雷击过电压、架空线断线时的相位不平衡等。

尽管要求如此严格,但一步一步解决问题时,实施起来却相当简单。

综合考虑,“Arduino Nano 3.0”板成为了该计划的“大脑”。 Robotdyn 板有一个 ATMEGA 328 控制器,这是必要的 3,3V 稳压器
电流 800 mA 和 CH340G UART-USB 转换器。

首先,运行时间计数器被创建为最新的。以前使用的安装在带有无变压器电源电路的 PIC 上的工业仪表在运行一年内会因电压浪涌而发生故障。只有使用自制 5V 电源连接的部分保持完好。为了加速安装和连接的多功能性,从开关设备的端子获取有关单元状态的信号,即使用 1V 三相电源记录第一相电压的存在。为了与控制器配合,采用380V绕组的中间继电器或由LED和GL220光敏电阻或PC5516光耦组成的光耦。所有选项均经过测试。 LED 由具有电流限制的整流电压供电,使用两个串联连接的 SVV817​​22 电容器设计用于 630V 电压,以确保在使用兆欧表意外测试电路时的安全性。
使用 ST7735S LCD 屏幕读取运行时间读数,使用 E01-ML01DP05 模块以 2,4 MHz 的频率通过无线电进行实时数据传输。该器件包含 nRF24L01+ 芯片和 RFX2401C 发送/接收放大器,
输出功率高达 100 mW。螺旋天线专为在线计算器中所需的范围而设计 сайта。天线类型的选择取决于排除从周围金属结构接收单个反射波的情况。天线部件是在 3D 打印机上打印的。计数器的当前状态存储在控制器本身的 EEPROM 中,并在意外断电时恢复。计数的时间间隔由带有备用电池的模块形式的RTC芯片DS3231提供。电源采用3个模块,实际脉冲源220/5V HLK-PM01 600mA,1-5V转5V转换器 HW-553 и 03962A - 电池控制器 方案 防止短路、过放电和过充电。所有组件均在 Aliexpress 网站上购买。

面包板本地自主数据采集系统
4通道计数器。输入端有 LC 滤波器,可防止双绞线通信线路受到干扰。有关控制对象状态的数据每秒持续读取一次,并以彩色显示在 LCD 上。读数每 1 秒更新一次并记录在非易失性存储器中。 36 秒是一小时的 36/1,这是数据所需的格式。每 100 秒一次。传输有关每个控制单元的操作秒数的信息。 EEPROM 存储器的写入-擦除循环次数有限,根据制造商的说法,为 12 次。最糟糕的选择是至少有一个单元不断更新。第一个计数器的容量为100000个字节,这是一个长格式的数字,1个计数器,一条记录总共占用4个字节。芯片内存长度为4字节,16个计数器的1024个条目后,将重新开始记录。在 EEPROM 库中,EEPROM.put 方法不写入;如果单元的值和正在写入的信息匹配,则单元不会退化。因此,保证内存运行时间将超过64年。可能但不能保证的工作时间可能会更长。

电路原理图本地自主数据采集系统
Arduino IDE 中的程序//12 字节 (328%)

#包括// 核心图形库
#include // 硬件特定库
#包括
#include
#包括
#include
#include
RF24 无线电(9, 10); // 用于使用 RF24 库的无线电对象,
// 和引脚号 nRF24L01+ (CE, CSN)
#包括
DS3231 实时时钟(SDA、SCL);
时间t;

//#定义TFT_CS 10
#定义TFT_CS 8
#define TFT_RST -1 //您也可以将其连接到Arduino重置
// 在这种情况下,将此 #define pin 设置为 -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);
#包括

字节移位= 52;
字节引脚状态;
unsigned long Pump[4];// 具有 4 秒计数器值的数组
浮动米= 3600.0;
无符号整型地址=0;
int rc;// 计数器变量
无符号长 sumprim = 0;
无符号长 sumsec = 0;
字节 i = 0;
字节 k = 34;
无符号整数 z = 0;
字节 b = B00000001;
字节 pumrcounter[4]; // 用于存储对象状态的数组,1 - 关闭,0 - 开启。
int 开始 = 0; //

无效设置(){

rtc.begin();
radio.begin(); // 启动 nRF24L01+ 工作
无线电.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 月 XNUMX 日

tft.initR(INITR_BLACKTAB); //初始化ST7735S芯片,黑色标签
// 如果您使用的是 1.44" TFT,请使用此初始化程序(取消注释)
//tft.initR(INITR_144GREENTAB); //初始化ST7735S芯片,红色rcB选项卡
tft.setTextWrap(假); // 允许文本超出右边缘
tft.setRotation( 2 ); // 对于黑色 PCB 和红色 tft.setRotation(0) 是否。
tft.fillScreen(ST7735_BLACK); //清屏

DDRD = DDRD | B00000000;
端口 = 端口 | 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("开发人员和构建"); // 赞美自己所爱的人
tft.setCursor(24, 10); // 或者邪恶的版权
tft.print("开发者 M.M.");
tft.setCursor(28, 20);
tft.print("BUILD-ER D.D.");

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

for ( z = 0; z < 1023; z += 16 ) { // 迭代行业的所有单元格
//并写入4个泵变量的数组,每个计数器4个字节,因为
// 无符号长变量。有 4 个计数器,所有 4 个计数器的一条记录占用 16 个字节。
EEPROM.get(z, 泵[0]); // 因此,没有 for 循环,体积更小
EEPROM.get(z+4, 泵[1]);
EEPROM.get(z+8, 泵[2]);
EEPROM.get(z+12, 泵[3]);

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

// 将 sumprim 变量中 4 个计数器总和的新值与该变量中的先前值进行比较
// sumsec,如果先前的总和小于或等于新的总和,则分配新的大于或等于的值
// 总和秒值。

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

//并将当前值z赋给地址变量,z是16个值的4字节块的开头地址
// 同时记录的计数器(因为轮询端口时,它的所有 8 位都会同时写入,
// 包括端口 D 所需的高 4 位)。
地址=z;
}
}

// 再次访问eeprom存储器的16字节块的开头地址,该块包含4个记录的计数器值
// 最后,即由于冻结而关闭或重新启动之前的值。记录最新的
// 将计数器值放入一个由 4 个变量组成的数组中 Pump。

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

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

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

AttachInterrupt(0, 计数, 上升); // 引脚D2,使能中断,每秒来一次
// 来自 SQW 输出的 RTC DS3231 脉冲

wdt_启用(WDTO_8S); // 启动看门狗定时器,在冻结的情况下重新启动控制器,时间,
// 为此,您需要发出计时器重置命令 wdt_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
}
// 颜色控制对象的状态指示
// 蓝色是现有屏幕(或库?)的一个小故障,RGB 和 BGR 混合在一起。
if (pinState == ( b << rc )) {
tft.fillRect(15, ((rc * 10 + shift)), 7, 7, ST7735_BLUE); // 对于低级别计数,将绿色更改为蓝色
} {
tft.fillRect(15, ((rc * 10 + 移位)), 7, 7, ST7735_GREEN); // 对于低级别计数,将蓝色更改为绿色
泵[rc] += 1; // 操作时间计数器加 1 秒
}
}

k++;
如果(k==36){
k = 0;

tft.fillRect(30, 移位, 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(泵[rc] / m);
}

// 将“原始”运行时间值(以秒为单位)写入 EEPROM ////////////////////////////////

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

// 通过无线电信道发送数据,指示应发送多少字节。
如果((k == 6)||(k == 18)||(k == 30)){

无符号长数据;

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

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

最后有一些注释。计数发生在输入的低逻辑电平。

对于带有光敏电阻 GL2 的选项,上拉电阻 R5-R36 为 5516 kOhm。对于光电晶体管光耦合器和继电器,设置为 4,7-5,1 kOhm。 Arduino Nano v3.0 引导加载程序已替换为 Arduino Uno,使用 TL866A 编程器来确保看门狗定时器的正确操作。保险丝经过校正,可在高于 4,3 V 的电压下工作。未使用外部复位电路 R6 C3。在示例程序中,发射机频率不对应于免许可范围;2,4 MHz 范围仅限于频率 2400.0-2483.5 MHz。

E01-ML01DP05 发射器的范围为 2400-2525 MHz。一个通道的带宽为1 MHz,当设置速率为“RF24_2MBPS”时,指定的radio.setChannel(120)通道将被占用,即下一通道被占用。频段为 2 MHz。

来源: habr.com

添加评论