Design of bridge monitoring data acquisition and management system based on multi-protocol sensors


foreword

1. Requirements:

1. MCU data acquisition and host computer communication:
use STM32F103 development board + AHT20 to simulate the temperature and humidity data acquisition of multiple monitoring points. Use the serial port/485 bus to complete the data transmission between the acquisition terminal and the host computer. The upper computer can run the Raspberry Pi 3B+ of the Linux system (the Raspberry Pi has serial ports and wired and wireless networks). If there is no real Raspberry Pi, it can be simulated by PC, and realized by standard C language or python programming.
2. Remote acquisition of sensor simulation data:
research content includes: RS485 bus and ModBus communication protocol, database technology, network communication programming development.
The upper computer completes remote periodic (such as 30 seconds) real-time collection and storage of at least two types of data (such as temperature, humidity, and stress) through UDP/TCP sockets and Modbus application layer protocols. The collected data is written into the Mysql database, and Mysql can be installed on the Win10 or Ubuntu system on the local PC. A collection data record includes at least: time stamp, collection point number, collection data type, collection data information. There is no limitation on the use of programming software for software development.
3. Thinking:
For the complex and changeable technical requirements of multi-sensors, multi-protocols, and multi-networking methods in actual engineering applications, if the flexible customization features of FPGA development board programming are used to design and implement different interface protocols, is it reasonable? sex? What are the advantages and disadvantages? Please briefly compare and analyze.

Note: It is mainly the design and programming debugging of the scheme.

2. System block diagram

2.1 Overall system block diagram

insert image description here

2.2. stm32 collects temperature and humidity block diagram through AHT20:

insert image description here

We plan to use AHT20 temperature and humidity sensor for this module, communicate with stm32 through I2C, and stm32 upload and communicate through ModBus protocol.

2.3. Block diagram of stm32 communicating with host computer through modbus protocol:

insert image description here

The host computer uses the Modbus protocol to send commands and accept data from the slave, and at the same time requires the host computer to store the received data in the database and read the deployed bridge sensors from the given dmo-monitor.igong.com The data.

3. ModBus protocol

It can be seen from the above system block diagram that we use the modbus protocol more, and we will explain the content of the modbus protocol here.

1. Protocol overview

1. The Modbus protocol is a serial communication protocol published by Modicon (now Schneider Electric) in 1979 for the use of programmable logic controller (PLC) communication. The Modbus protocol is an application layer protocol, which has become the industry standard for communication protocols in the industrial field, and is a commonly used connection method between industrial electronic devices.
2. Modbus is a master/slave architecture protocol. One node is the master node, and other nodes that use the Modbus protocol to participate in communication are slave nodes. Each slave device has a unique address. Only the node designated as the master node can initiate a command. All Modbus data frames contain a check code to ensure the correctness of transmission. Basic ModBus commands can instruct a slave device to change a value in one of its registers, control or read an I/O port, and direct the device to send back data in one or more of its registers.

2. Principle of Modbus master/slave protocol

The Modbus serial link protocol is a master-slave protocol. At the same time, only one master station can be connected to the bus, and one or more slave stations (maximum number 247) can be connected to the same serial bus. Modbus communication is always initiated by the master station, when the slave station does not receive a request from the master station, it will not send data. The master station can only start one Modbus transaction at the same time, and the slave stations cannot communicate with each other.

insert image description here

3. General Modbus frame structure - protocol data unit (PDU)

The Modbus protocol defines a simple protocol data unit (PDU) independent of the underlying communication layer. Modbus protocol mapping on a specific bus or network can introduce some additional fields on the application data unit (ADU).

insert image description here

4. Two Modbus serial transmission modes

RTU mode : Each 8-bit byte contains two 4-bit hexadecimal characters. The advantage is that at the same baud rate, more data can be transmitted than ASCII, but each message must be in continuous data streaming.

insert image description here

ASCII mode : 2 ASCII characters are required for each 8-Bit byte in the information, which has the advantage of allowing the transmission interval of characters to reach 1s without error;

insert image description here

5. ModbusTCP communication structure

Communication devices for Modbus TCP/IP: Modbus TCP/IP client and server devices connected to a TCP/IP network.
Interconnection devices such as bridges, routers, or gateways that interconnect between TCP/IP networks and serial link subnets.

insert image description here

6. Communication protocol instructions involved in the system

insert image description here

7. Some protocol function codes

insert image description here

1. MCU data acquisition and host computer communication

1. Temperature and humidity collection (I2C protocol)

Temperature and humidity reading module The sensor we use here is AHT20 and I2C protocol . The I2C communication protocol (Inter-Integrated Circuit) was developed by Philps. Because it has few pins, simple hardware implementation, and strong scalability, it does not require external transceiver devices such as USART and CAN. It is now widely used
in Communication between multiple integrated circuits (ICs) in a system.

1. After power on, wait for a period of time and wait for the device to work normally before reading the temperature and humidity:

  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_USART1_UART_Init();
  uint32_t CT_data[2]={
    
    0,0};	
  volatile int  c1,t1;
  rt_thread_delay(50);
  AHT20_Init();
  rt_thread_delay(2500);

2. Read the temperature and humidity data after the CRC check, and then delay for 5 minutes


    AHT20_Read_CTdata_crc(CT_data);  //crc校验后,读取AHT20的温度和湿度数据 
	  c1 = CT_data[0]*100*10/1024/1024;  //计算得到湿度值c1(放大了10倍)
	  t1 = CT_data[1]*200*10/1024/1024-500;//计算得到温度值t1(放大了10倍)	
		printf("湿度:%d%s",c1/10,"%");
	  printf("温度:%d%s",t1/10,"℃");
	  printf("\r\n");
		rt_thread_mdelay(300000);//线程睡眠大约5分钟,挂起执行其他操作

2. Host computer communication

Here our requirement is to simulate the collection of temperature and humidity data at multiple monitoring points. Here we can adopt the multitasking framework of transplanting RT-thread Nano to prevent the normal operation of other sensors.

Enable the Modbus protocol in the main function and initialize the RT-Thread process:

eMBInit( MB_RTU, 0x01, 1, 115200, MB_PAR_NONE);//初始化modbus,走modbusRTU,从站地址为0x01,端口为1。
	eMBEnable();//使能modbus
	MX_RT_Thread_Init();	//初始化 RT-Thread 进程

After configuring the AHT20 code and modbus driver files, import the relevant header files:

#include "rtthread.h"	// RT-Thread 头文件
#include "mb.h"	// Modbus 头文件
#include "mbport.h"	// Modbus 端口头文件
#include "AHT20.h"	// AHT20传感器驱动头文件
extern void MX_RT_Thread_Init(void);	// RT-Thread 初始化函数,初始化并执行各种进程
extern void MX_RT_Thread_Process(void);	// RT-Thread 主进程

Turn on multi-threading, the main task is modbus monitoring, and the sub-task is to test the program:

#include "rtthread.h"
#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"
#include "stdio.h"
#include "AHT20.h"
#include "mb.h"
#include "mbport.h"
 
struct rt_thread led1_thread;
rt_uint8_t rt_led1_thread_stack[128];
void led1_task_entry(void *parameter);
 
//初始化线程函数
void MX_RT_Thread_Init(void)
{
    
    
	//初始化LED1线程
	rt_thread_init(&led1_thread,"led1",led1_task_entry,RT_NULL,&rt_led1_thread_stack[0],sizeof(rt_led1_thread_stack),3,20);
	//开启线程调度
	rt_thread_startup(&led1_thread);
}
 
//主任务
void MX_RT_Thread_Process(void)
{
    
    
	(void)eMBPoll();	//启动modbus监听
}
 
//LED1任务
void led1_task_entry(void *parameter)
{
    
    
	while(1)
	{
    
    
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13, GPIO_PIN_RESET);
		rt_thread_delay(500);
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13, GPIO_PIN_SET);
		rt_thread_delay(500);
	}

}

Modify the function code to 04 in the eMBRegInputCB function to read the input register:

eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
    
    
	eMBErrorCode eStatus = MB_ENOERR;
	int iRegIndex;
	int i;
	InputBuff[0] = 0x11;
	InputBuff[1] = 0x22;
	InputBuff[2] = 0x33;
	InputBuff[3] = 0x44;
	
	if( ( usAddress >= REG_INPUT_START ) && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
	{
    
    
		iRegIndex = ( int )( usAddress - usRegInputStart );
		for(i=0;i<usNRegs;i++)
		{
    
    
			*pucRegBuffer=InputBuff[i+usAddress-1]>>8;
			pucRegBuffer++;
			*pucRegBuffer=InputBuff[i+usAddress-1]&0xff;
			pucRegBuffer++;
		}
	}
	else
	{
    
    
		eStatus = MB_ENOREG;
	}
 
	return eStatus;
}

In the output function eMBRegInputCB, store the returned temperature and humidity data in the InputBuff[] array for output:

eMBErrorCode eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
    
    
	eMBErrorCode eStatus = MB_ENOERR;
	int iRegIndex;
	int i;
	
	HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);	// 使用 PC13 引脚上的板载小灯泡进行测试——小灯泡亮
	AHT20_Read_CTdata_crc(CT_data);       //经过CRC校验,读取AHT20的温度和湿度数据    推荐每隔大于1S读一次
	c1 = CT_data[0]*1000/1024/1024;  //计算得到湿度值c1(放大了10倍)
	t1 = CT_data[1]*2000/1024/1024-500;//计算得到温度值t1(放大了10倍)
	t2 = t1/10 + (t1/10)%10;	//温度的整数部分
	t3 = t1%10;	//温度的小数部分
	c2 = c2/10 + (c1/10)%10;	// 湿度的整数部分
	c3 = c3%10;	//湿度的小数部分
	
	InputBuff[0] = t2;
	InputBuff[1] = t3;
	InputBuff[2] = c2;
	InputBuff[3] = c3;
	
	if( ( usAddress >= REG_INPUT_START ) && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
	{
    
    
		iRegIndex = ( int )( usAddress - usRegInputStart );
		for(i=0;i<usNRegs;i++)
		{
    
    
			*pucRegBuffer=InputBuff[i+usAddress-1]>>8;
			pucRegBuffer++;
			*pucRegBuffer=InputBuff[i+usAddress-1]&0xff;
			pucRegBuffer++;
		}
	}
	else
	{
    
    
		eStatus = MB_ENOREG;
	}
 
	return eStatus;
}

Since there is no AHT20 module in hand, the demonstration of the effect cannot be performed. Here is only a general description of the process and a display of some important module codes.

2. Remote collection of sensor simulation data

1.TCP socket and modbus protocol

In the content of establishing connection with the remote data service through the TCP protocol, the collection of bridge stress and temperature is mainly completed.

crc check:

def crc16(string):
    #data = bytes.fromhex(string)
    data=string
    crc = 0xFFFF
    for pos in data:
        crc ^= pos
        for i in range(8):
            if ((crc & 1) != 0):
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return hex(((crc & 0xff) << 8) + (crc >> 8))

Database Connectivity:

def MySQLConnect():
    connection = pymysql.connect(
        host='localhost',  # IP,MySQL数据库服务器IP地址
        port=3306,  # 端口,默认3306,可以不输入
        user='root',  # 数据库用户名
        password='密码',  # 数据库登录密码
        database='sensor',  # 要连接的数据库
        charset='utf8'  # 字符集,注意不是'utf-8'
    )
    return connection

Insert data into the database:

def AddData(num,yb,wd,time):
    # 连接数据库
    conn = MySQLConnect()
    # 使用cursor()方法创建一个游标对象cursor
    cursor = conn.cursor()
    # 插入数据库
    sql = "INSERT INTO strain_sensor(id ,mic, strain_temp, time) VALUES (%s,%s,%s,%s); "
    cursor.execute(sql, [num,yb, wd, time])
    # 提交事务
    conn.commit()
    # 关闭游标
    cursor.close()
    # 关闭数据库连接
    conn.close()

retrieve data:

def getStain(cmd,num,time):
    #print(cmd)
    #print(num)
    cmd = bytes.fromhex(cmd)
    crc = crc16(cmd)
    crc = bytes.fromhex(crc[2:])
    cmd = cmd + crc
    #print(cmd)
    #发送对应的指令
    tcp.send(cmd)
    try:
        data = tcp.recv(8192)
    except socket.timeout:
        print("超时")
        sys.exit(1)
    crc = data[-2:]
    crc1 = crc16(data[:-2])
    crc1 = crc1[2:]
    if len(crc1) == 3:
        crc1 = '0' + crc1
    crc1 = bytes.fromhex(crc1)
    if crc != crc1:
        print("CRC16校验失败!")
        sys.exit(2)
    yb, wd = struct.unpack('>ii', data[4:12])
    yb = yb / 100.0
    wd = wd / 100.0
    print("应变:", yb, "温度:", wd)
    print(time)
    yb = str(yb)
    wd = str(wd)
    AddData(num, yb, wd, time)

Establish a TCP connection:
insert image description here
insert image description here

Effect:
No. 3 sensor collects strain force and temperature information:
insert image description here
database:
insert image description here

2. UDP socket and modbus protocol

In the content of obtaining data from the remote bridge monitoring data service system using the UDP protocol, we have realized the collection of temperature sensors and information collection of static levels.

CRC check:

def crc16(string):
    #data = bytes.fromhex(string)
    data=string
    crc = 0xFFFF
    for pos in data:
        crc ^= pos
        for i in range(8):
            if ((crc & 1) != 0):
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return hex(((crc & 0xff) << 8) + (crc >> 8))

Database Connectivity:

def MySQLConnect():
    connection = pymysql.connect(
        host='localhost',  # IP,MySQL数据库服务器IP地址
        port=3306,  # 端口,默认3306,可以不输入
        user='root',  # 数据库用户名
        password='password',  # 数据库登录密码
        database='sensor',  # 要连接的数据库
        charset='utf8'  # 字符集,注意不是'utf-8'
    )

Insert the obtained temperature and humidity timestamp into the database:

def AddData1(wd,sd,time):
    # 连接数据库
    conn = MySQLConnect()
    # 使用cursor()方法创建一个游标对象cursor
    cursor = conn.cursor()
    # 插入数据库
    sql = "INSERT INTO temp_hum_sensor(temp, hum, time) VALUES (%s,%s,%s); "
    cursor.execute(sql, [wd, sd, time])
    # 提交事务
    conn.commit()
    # 关闭游标
    cursor.close()
    # 关闭数据库连接
    conn.close()

The obtained sensor id, deflection, and timestamp are stored in the database:

def AddData2(id,water_level,time):
    # 连接数据库
    conn = MySQLConnect()
    # 使用cursor()方法创建一个游标对象cursor
    cursor = conn.cursor()
    # 插入数据库
    sql = "INSERT INTO static_level(id, water_level, time) VALUES (%s,%s,%s); "
    cursor.execute(sql, [id, water_level, time])
    # 提交事务
    conn.commit()
    # 关闭游标
    cursor.close()
    # 关闭数据库连接
    conn.close()

Temperature and humidity collection process (modbus):

def getDataTemp(cmd):
    #flag标志采集的次数
    flag=0
    last = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    print(last)
    last1 = time.time()
    cmd = bytes.fromhex(cmd)
    #print(cmd)
    crc = crc16(cmd)
    crc = bytes.fromhex(crc[2:])
    #得到发送的指令(modbus协议定义内容+校验)
    cmd = cmd + crc
    udp.sendto(cmd, ('demo-monitor.igong.com', 8001))
    try:
        data, addr = udp.recvfrom(8192)
    except socket.timeout:
        print("超时")
        sys.exit(1)
    crc = data[-2:]
    crc1 = crc16(data[:-2])
    crc1 = crc1[2:]
    if (len(crc1) == 3):
        crc1 = '0' + crc1
    crc1 = bytes.fromhex(crc1)

    # print(crc1)
    if crc != crc1:
        print("CRC16校验失败!")
        sys.exit(2)
    # 解析数据
    wd, sd = struct.unpack('>ii', data[4:12])
    wd = wd / 100.
    print("温度:", wd, "湿度:", sd)
    AddData1(wd, sd, last)
    flag=flag+1
    while True:
        now= time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        #print(s)
        now1=time.time()
        #每隔5s获取一次数据
        if(now1-last1>5):
            udp.sendto(cmd, ('demo-monitor.igong.com', 8001))
            try:
                data, addr = udp.recvfrom(8192)
            except socket.timeout:
                print("超时")
                sys.exit(1)
            crc = data[-2:]
            crc2=bytes.hex(crc)
            #print(crc2)
            crc1 = crc16(data[:-2])
            crc1=crc1[2:]
            if(len(crc1)==3):
                crc1='0'+crc1
            #print(crc1)
            crc1=bytes.fromhex(crc1)
            #print(crc1)
            if crc != crc1:
                print("CRC16校验失败!")
                sys.exit(2)
            #解析数据
            wd, sd = struct.unpack('>ii', data[4:12])
            wd = wd / 100.0
            #当前时间
            print(now)
            #获取得到的数据
            print("温度:", wd, "湿度:", sd)
            last=now
            last1=now1
            wd=str(wd)
            sd=str(sd)
            AddData1(wd,sd,now)
            flag = flag + 1
            if flag >= 5:
                str1 = input("请选择是否继续采集(y表示继续,n表示退出):")
                if str1 == 'y':
                    flag = 0
                    continue
                else:
                    break

insert image description here
Select sensor:

def getDataStaticLevel(cmd):
    id=cmd[0:2]
    #print(id)
    if id=='02':
        #print("2号")
        id='00'+id
        getData(id,cmd)
    elif id=='03':
        #print("3号")
        id = '00' + id
        getData(id,cmd)
    elif id=='04':
        #print("4号")
        id = '00' + id
        getData(id,cmd)
    elif id=='05':
        #print("5号")
        id = '00' + id
        getData(id,cmd)

To establish a connection with remote data:
insert image description here

insert image description here
Effects:
Temperature Humidity Module:
insert image description here
Database:
insert image description here
Deflection:
insert image description here
Database:
insert image description here

3. Thinking questions

For the complex and changeable technical requirements of multi-sensors, multi-protocols, and multi-networking methods in actual engineering applications, is it reasonable to use the flexible customization features of FPGA development board programming to design and implement different interface protocols? What are the advantages and disadvantages? Please briefly compare and analyze.

I think it is reasonable, because the programming flexibility and data processing capability of fpga itself are enough to support him to implement multiple protocols. Advantages: The current mid-range FPGA is already experimenting with different interface protocols, and the second is the ability to obtain FPGA processing information. Disadvantages: It will cost more to build a complete protocol stack, and it needs to go through many experiments. Even if it passes, there are still hidden dangers in information security.


Four. Summary

The most important protocol of this project design is modbus, which has been used in previous assignments, but in this design process, it has deepened understanding and familiarity. Due to the lack of support of hardware resources, the content of the first part is mainly based on the homework that has been realized before, and it is enough to explain and review. In the second part of the connection to the remote detection data service, two connection methods, UDP\TCP, are used, but the most important thing is to understand the implementation process of modbus communication in the code. So this design has gained a lot from the study of modbus!

Guess you like

Origin blog.csdn.net/qq_52215423/article/details/128703805