admin 管理员组

文章数量: 887021

物联网工程感知课设

  • 一.功能分析
  • 二.概要设计
    • 1.系统组成
    • 2.传感器选型
  • 三.详细设计
    • 1.硬件连接
    • 2.程序设计
    • 3.界面设计
  • 四.系统说明
    • 1. 硬件设备
    • 2. 软件程序
    • 3. 系统实现步骤
  • 五.设计总结
    • 心得体会:
  • 六.附录
    • 源程序文件名清单
  • 七.问题分析
  • 八.系统可改进

本项目文件已经开源在github上面:https://github/fengqianiqan/temperatureDetectSystem_fq/tree/master

一.功能分析

环境监测系统主要包括对环境变量的采集和显示。

1.选择合适的传感器来完成温度、湿度、光照数据的采集。

(1)传感器选择:选择合适的传感器来完成温度、湿度、光照数据的采集。对于不同的环境监测场景,可以选择不同类型的传感器,比如温度传感器、湿度传感器、光照传感器等。同时,需要考虑传感器的精度、灵敏度、可靠性等因素。

2.将串口与数据库连接,将实时数据存放在数据库中。

(1)数据处理:采集到的数据需要进行处理和分析,以便对环境的变化和趋势进行监测和预测。数据处理可以包括数据清洗、数据可视化、数据挖掘等技术,需要根据监测目的和实际需求进行定制。

(2)数据存储:将采集到的实时数据存储在数据库中,这里可以选择关系型数据库或者NoSQL数据库。在存储数据时,需要考虑数据库的性能、可靠性、容量等因素。

(3)数据展示:通过数据可视化技术,将存储在数据库中的数据以图表、曲线等形式展示出来,以便用户更直观地了解环境变化的趋势和规律。

3.制作相应的显示界面,将采集的变量值实时显示。

(1)数据采集:选定传感器后,需要将其与数据采集设备或者嵌入式系统相连接,实现数据的实时采集和传输。数据采集设备可以是单片机、嵌入式计算机、传感器网络等,需要考虑设备的处理能力、通信方式、数据存储等因素。

(2)数据处理:采集到的数据需要进行处理和分析,以便对环境的变化和趋势进行监测和预测。数据处理可以包括数据清洗、数据可视化、数据挖掘等技术,需要根据监测目的和实际需求进行定制。

(3)数据展示:制作相应的显示界面,将采集的变量值实时显示。可以通过人机界面、手机APP、网页等方式展示数据,以便用户更直观地了解环境变化的趋势和规律。

  1. 扩展功能:判断温度过高过低、湿度过高过低时,通过电机控制蜂鸣器发出声响。
  2. 报警与控制:当监测到环境参数超出预设范围时,需要触发报警机制,并通过电机控制蜂鸣器发出声响,以便及时采取措施避免环境事故的发生。这里需要根据实际需求选择合适的电机和蜂鸣器,并通过嵌入式系统或者数据采集设备控制其工作。

5.采集的输入变量及其形式:

(1)温度:摄氏度或华氏度的数字值,例如25°C或77°F。

(2)湿度:相对湿度的百分比,例如50%。

(3)光照:光照强度的数字值,例如1000勒克斯。

(4)传感器的标识符:传感器传入数据的id

(5)采集数据的时间戳:接收数据的时间,例如使用字符串的字符类型输入,在数据库内进行存储。

6.输出的变量及其形式:

(1)温度:摄氏度或华氏度的数字值,例如25°C或77°F。

(2)湿度:相对湿度的百分比,例如50%。

(3)光照:光照强度的数字值,例如1000勒克斯。

(4)传感器的标识符:传感器传入数据的id

(5)采集数据的时间戳:接收数据的时间,例如可以通过显示屏、报表、图形化界面、API等形式进行输出。

7.程序所能达到的功能

(1)采集环境参数数据:通过传感器采集环境参数数据,包括温度、湿度、光照、声音、空气质量、水质等。

(2)存储和管理数据:将采集的数据存储在数据库或其他存储系统中,进行正确的数据管理和分析。这包括数据的标记、时间戳、备份和还原等操作。

(3)分析数据:对采集的数据进行处理和分析,以提取有用的见解和模式。这包括数据的统计分析、机器学习、时间序列分析等方法。

(4)可视化数据:以图表、图形化界面等形式呈现分析后的数据,使用户能够更好地理解数据中的模式和趋势。

发出警报和通知:根据预先设定的阈值或规则,发出警报和通知,以提醒用户系统中的异常情况。

(5)生成报告和记录:生成详细的报告和记录,包括数据分析、警报和通知、系统状态等信息,以帮助用户更好地了解系统的运行情况和趋势。

二.概要设计

1.系统组成

环境监测系统通常由以下组成部分构成:

  1. 传感器和仪表:用于检测环境中的各种参数,例如温度、湿度、光照等。
  2. 数据采集器:用于将传感器和仪表收集到的数据进行采集和处理,然后将数据传输到数据处理单元。
  3. 数据处理单元:用于处理和分析传感器和仪表收集到的数据,并将其转换为可读的格式,例如图表或报告。
  4. 数据存储单元:用于存储处理后的数据,并提供数据查询和检索功能。
  5. 通信网络:用于将数据传输到监测中心或其他设备,例如报警器或监视器。

本系统大体组成包括:传感器模块、数据传送模块和电机控制模块。系统框图如图1所示。由于传感器模块没有外接电路,因此需要通过中间的协调器将数据转为串口形式发送到PC机上。

图1 系统框图

2.传感器选型

温度传感器:用于监测环境温度,适用于各种气体和液体的温度监测。

湿度传感器:用于监测环境湿度,适用于各种气体和液体的湿度监测。

光照传感器:用于监测环境光照强度,适用于各种光照环境的监测。

选择SHT10单片数字温湿度传感器来监测环境。SHT10采用CMOSens专利技术将温度湿度传感器、A/D转换器及数字接口无缝结合,使传感器具有体积小、响应速度快、接口简单、性价比高等特点。

SHT10的主要技术特点包括:

  1. 高精度:温度测量精度为±0.5℃,湿度测量精度为±3%RH。

高稳定性:传感器的长期稳定性和可靠性非常好。

  1. 全球通用:支持多种信号输出方式,包括PWM输出、I2C总线输出、单线串行输出和模拟输出等,适用于各种应用场合。
  2. 低功耗:采用低功耗设计,工作电压为2.4V-5.5V,静态电流仅为80nA。
  3. 快速响应:传感器的响应时间非常快,温度测量响应时间为1秒,湿度测量响应时间为8秒。
  4. 高抗干扰能力:传感器采用数字信号输出,具有较强的抗干扰能力,能够有效地抵抗电磁干扰和温度变化等因素的影响。

电路连接时,接口简单,两线连接,SHT10的两线串行接口(bidirectional 2-wire)在传感器信号读取和电源功耗方面都做了优化处理,其总线类似I2C总线但并不兼容I2C总线。

三.详细设计

1.硬件连接

SHT10是一种数字温湿度传感器,它可以通过I2C或者单线接口进行硬件连接。

下面是使用I2C接口连接SHT10的步骤:

  1. 将SHT10的VDD引脚连接到3.3V电源,将GND引脚连接到地。

  2. 将SHT10的SCL引脚连接到主控板的I2C时钟线,通常为SCL或SCL1。

  3. 将SHT10的SDA引脚连接到主控板的I2C数据线,通常为SDA或SDA1。 如果需要使用SHT10的电源控制引脚(SHT10上的DATA引脚),则将其连接到主控板的GPIO引脚。

  4. 确保I2C总线上的上拉电阻正确连接。通常会在主控板上提供。

    下面是使用单线接口连接SHT10的步骤:

  5. 将SHT10的VDD引脚连接到3.3V电源,将GND引脚连接到地。

  6. 将SHT10的DATA引脚连接到主控板的GPIO引脚。需要在主控板上使用一个上拉电阻将DATA引脚连接到3.3V电源。

在程序中使用单线协议来读取SHT10的温湿度数据。

需要注意的是,SHT10的数据线(SCL或DATA)必须连接到一个上拉电阻,以确保正确的信号传输。另外,在使用单线接口时,需要使用特定的协议来读取SHT10的数据,具体实现方法可以参考SHT10的数据手册。

传感器接口定义如下:

图2 SHT接口简介

SHT10共有4个引脚,除了电源和地,数据和时钟引脚分别连接单片机P06、P07。

图3 系统硬件框图

2.程序设计

(1)端口初始化程序

static void GPIOInit(void)

{

P0SEL &= \~(1\<\<6); //时钟接口初始化,IO口功能选择

P0DIR \|= (1\<\<6); //IO口方向选择

P0SEL &= \~(1\<\<7); //数据接口初始化

P0DIR \|= (1\<\<7); //IO口方向选择

}

功能:初始化SHT10接口; 入口参数:无; 返回值:无。

(2)传感器采集程序

static uint16 ReadSHT10(uint8 param)

{

double temp;

uint8 i;

uint16 result;

uint16 SORH = 0;

DATA_OUTPUT;

DATA_HIGH;

SCK_OUTPUT;

SCK_LOW;

//通讯复位

for( i=0; i\<10; i++ )

{

SCK_HIGH;

MicroWait(30);

SCK_LOW;

MicroWait(30);

}

……

功能:读取SHT10的温湿度值; 入口参数:0x00,温度; 0x01,湿度; 返回值:温湿度值。

图4 传感器工作时序图

SHT10工作时,要通过SCK引脚模拟时序来完成,因此,读传感器的数据时,需要单片机控制SCK产生一系列时序,配合DATA的变化以完成温湿度的数据采集。

对于采集到的湿度值需要通过以下的公式进行换算:

同样,温度值要经过以下换算,才能得到实际值,这些都在传感器的读写程序里完成。

后端部分代码:

(1)监听器

1.	// 监听器,我的理解是独立开辟一个线程监听串口数据  
2.	static CommPortIdentifier portId; // 串口通信管理类  
3.	static Enumeration<?> portList; // 有效连接上的端口的枚举  
4.	InputStream inputStream; // 从串口来的输入流  
5.	static OutputStream outputStream;// 向串口输出的流  
6.	static SerialPort serialPort; // 串口的引用  
7.	// 堵塞队列用来存放读到的数据  
8.	private BlockingQueue<String> msgQueue = new LinkedBlockingQueue<String>(); 

(2)持续监听端口上是否有数据流

1.	/** 
2.	 * SerialPort EventListene 的方法,持续监听端口上是否有数据流 
3.	 */  
4.	public void serialEvent(SerialPortEvent event) {//  
5.	  
6.	    switch (event.getEventType()) {  
7.	        case SerialPortEvent.BI:  
8.	        case SerialPortEvent.OE:  
9.	        case SerialPortEvent.FE:  
10.	        case SerialPortEvent.PE:  
11.	        case SerialPortEvent.CD:  
12.	        case SerialPortEvent.CTS:  
13.	        case SerialPortEvent.DSR:  
14.	        case SerialPortEvent.RI:  
15.	        case SerialPortEvent.OUTPUT_BUFFER_EMPTY:  
16.	            break;  
17.	        case SerialPortEvent.DATA_AVAILABLE:// 当有可用数据时读取数据  
18.	            byte[] readBuffer = new byte[20];  
19.	            try {  
20.	                int numBytes = -1;  
21.	                while (inputStream.available() > 0) {  
22.	                    numBytes = inputStream.read(readBuffer);  
23.	                    StringBuilder sb = new StringBuilder();  
24.	                    for(byte b:readBuffer){  
25.	                        sb.append(String.format("%02x",b));  
26.	                    }  
27.	                    if (numBytes > 0) {  
28.	                        msgQueue.add(new Date() + "真实收到的数据为:-----"  
29.	                                + new String(sb));  
30.	                        readBuffer = new byte[20];// 重新构造缓冲对象,否则有可能会影响接下来接收的数据  
31.	                    } else {  
32.	                        msgQueue.add("额------没有读到数据");  
33.	                    }  
34.	                }  
35.	            } catch (IOException e) {  
36.	            }  
37.	            break;  
38.	    }  
39.	}  

(3)通过程序打开COM4串口,设置监听器以及相关的参数和数据库的连接

1.	/** 
2.	    * 
3.	    * 通过程序打开COM4串口,设置监听器以及相关的参数 
4.	    * 
5.	    * @return 返回1 表示端口打开成功,返回 0表示端口打开失败 
6.	    */  
7.	   public int startComPort() {  
8.	       // 通过串口通信管理类获得当前连接上的串口列表  
9.	       portList = CommPortIdentifier.getPortIdentifiers();  
10.	       String url="jdbc:mysql://127.0.0.1:3306/zigbee1?characterEncoding=utf-8";  
11.	       String user="root";  
12.	       String password = "111111";  
13.	       try {  
14.	           Class.forName("com.mysql.jdbc.Driver");  
15.	       } catch (ClassNotFoundException e2) {  
16.	           // TODO Auto-generated catch block  
17.	           e2.printStackTrace();  
18.	       }  
19.	       try {  
20.	           ct=DriverManager.getConnection(url,user,password);  
21.	       } catch (SQLException e1) {  
22.	           // TODO Auto-generated catch block  
23.	           e1.printStackTrace();  
24.	       }  
25.	       while (portList.hasMoreElements()) {  
26.	  
27.	           // 获取相应串口对象  
28.	           portId = (CommPortIdentifier) portList.nextElement();  
29.	  
30.	           System.out.println("设备类型:--->" + portId.getPortType());  
31.	           System.out.println("设备名称:---->" + portId.getName());  
32.	           // 判断端口类型是否为串口  
33.	           if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {  
34.	               // 判断如果COM4串口存在,就打开该串口  
35.	               if (portId.getName().equals("COM8")) {  
36.	                   try {  
37.	                       // 打开串口名字为COM_4(名字任意),延迟为2毫秒  
38.	                       serialPort = (SerialPort) portId.open("COM8", 2000);  
39.	  
40.	                   } catch (PortInUseException e) {  
41.	                       e.printStackTrace();  
42.	                       return 0;  
43.	                   }  
44.	                   // 设置当前串口的输入输出流  
45.	                   try {  
46.	                       inputStream = serialPort.getInputStream();  
47.	                       outputStream = serialPort.getOutputStream();  
48.	                   } catch (IOException e) {  
49.	                       e.printStackTrace();  
50.	                       return 0;  
51.	                   }  
52.	                   // 给当前串口添加一个监听器  
53.	                   try {  
54.	                       serialPort.addEventListener(this);  
55.	                   } catch (TooManyListenersException e) {  
56.	                       e.printStackTrace();  
57.	                       return 0;  
58.	                   }  
59.	                   // 设置监听器生效,即:当有数据时通知  
60.	                   serialPort.notifyOnDataAvailable(true);  
61.	  
62.	                   // 设置串口的一些读写参数  
63.	                   try {  
64.	                       // 比特率、数据位、停止位、奇偶校验位  
65.	                       serialPort.setSerialPortParams(115200,  
66.	                               SerialPort.DATABITS_8, SerialPort.STOPBITS_1,  
67.	                               SerialPort.PARITY_NONE);  
68.	                   } catch (UnsupportedCommOperationException e) {  
69.	                       e.printStackTrace();  
70.	                       return 0;  
71.	                   }  
72.	  
73.	                   return 1;  
74.	               }  
75.	           }  
76.	       }  
77.	/        System.err.println("行 75 portId.getName().equals(\"COM4:USB-SERIAL\")判fasle");  
78.	       return 0;  
79.	   }  

(4)温湿度设置上下界,并判断监测温度是否在界内

1.	if(temp_f>0&&temp_f<50) {  
2.	                        sql+=num+"','"+temp+"','"+humid+"','"+str1[0]+"')";  
3.	                        //System.out.println(sql);  
4.	                        s.executeUpdate(sql);  
5.	                        System.out.println(temp_f);  
6.	                        wendu1=temp_f;  
7.	                        shidu1=(float)Long.parseLong(humid_tmp,16)/100;  
8.	                        tf1.setText(String.valueOf((wendu1+"℃")));  
9.	                        tf2.setText(String.valueOf((shidu1+"%")));  
10.	                        if(wendu1>=w1&&wendu1<wx){  
11.	                            tf9.setText((String.valueOf("当前温度低于舒适温度")));  
12.	                        }else if(wendu1>wx&&wendu1<=w2) {  
13.	                            tf9.setText((String.valueOf("当前温度高于舒适温度")));  
14.	                        }else if(wendu1<wx||wendu1>w2){  
15.	                            tf9.setText((String.valueOf("当前温度超出范围")));  
16.	                            toolkit.beep();  
17.	                            Thread.sleep(1000);  
18.	  
19.	                        } else{  
20.	                            tf9.setText((String.valueOf("当前温度适宜")));  
21.	                        }  
22.	                        if(shidu1>=s2&&shidu1<sx){  
23.	                            tf10.setText(String.valueOf("当前湿度小,干燥"));  
24.	                        }else if(shidu1>sx&&shidu1<=s1){  
25.	                            tf10.setText(String.valueOf("当前湿度大:潮湿"));  
26.	                        }else if(shidu1>s2||shidu1<s1){  
27.	                            tf10.setText(String.valueOf("当前湿度超出范围!!!"));  
28.	                            toolkit.beep();  
29.	                            Thread.sleep(1000);  
30.	  
31.	  
32.	                        }else{  
33.	                            tf10.setText(String.valueOf("当前湿度适宜"));  
34.	                        }  
35.	  
36.	                        w1=Double.parseDouble(tf3.getText());  
37.	                        w2=Double.parseDouble(tf4.getText());  
38.	                        wx=Double.parseDouble(tf5.getText());  
39.	                        s1=Double.parseDouble(tf6.getText());  
40.	                        s2=Double.parseDouble(tf7.getText());  
41.	                        sx=Double.parseDouble(tf8.getText());  
42.	  
43.	                    }  

(5)检测光照强度,并将数据存入数据库

1.	 while (true) {  
2.	                // 如果堵塞队列中存在数据就将其输出  
3.	                if (msgQueue.size() > 0) {  
4.	                    num++;  
5.	                    Statement s=ct.createStatement();  
6.	                    String sql="insert into lightstrength (id,light,create_time) values('";  
7.	                    String get=msgQueue.take();  
8.	                    System.out.println(get);  
9.	                    String[] str1=get.split("真实收到的数据为:-----");  
10.	                    //光强  
11.	                    String light_tmp=str1[1].substring(10,14);  
12.	                    String light=Float.toString((float)Long.parseLong(light_tmp,16))+"lux";  
13.	                    if(!str1[1].substring(8, 10).equals("aa")) {  
14.	                        sql+=num+"','"+light+"','"+str1[0]+"')";  
15.	                        System.out.println("(白天室内正常为:300~500勒克斯(lux))目前光照强度是:"+light);  
16.	                        if((float)Long.parseLong(light_tmp,16)<300&&(float)Long.parseLong(light_tmp,16)>100){  
17.	                            System.out.println("光线较暗");  
18.	                        }  
19.	                        if((float)Long.parseLong(light_tmp,16)<100){  
20.	                            System.out.println("光线很暗");  
21.	                        }  
22.	                        s.executeUpdate(sql);  
23.	                    }  
24.	                    if(num%20==0){  
25.	                        s.executeUpdate("DELETE FROM lightstrength");  
26.	                    }  
27.	                }  
28.	            }  

前端部分代码:

(1)连接数据库,提取最新数据

1.	try {  
2.	        Class.forName("com.mysql.jdbc.Driver");  
3.	        connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/zigbee1?characterEncoding=utf-8","root","111111");  
4.	        String sql1 = "select * from lightstrength";  
5.	        String sql2 = "select * from zigbee_receive_data";  
6.	        statement = connection.createStatement();  
7.	  
8.	        resultSet = statement.executeQuery(sql1);  
9.	        out.println("</br><table align=\"center\" border=\"2px\">\n" +  
10.	                "    <tr>\n" +  
11.	                "    <th>id</th><th>光照强度</th><th>时间</th>\n" +  
12.	                "    </tr>");  
13.	            resultSet.next();  
14.	            int id = resultSet.getInt("id");  
15.	            String light = resultSet.getString("light");  
16.	            String time = resultSet.getString("create_time");  
17.	            out.println( "<tr>\n" +  
18.	                    " <td>"+id+"</td><td>"+light+"</td><td>"+time+"</td>\n" +  
19.	                    " </tr>");  
20.	            out.println("</table>");  
21.	  
22.	            resultSet = statement.executeQuery(sql2);  
23.	            out.println("</br><table align=\"center\" border=\"2px\">\n" +  
24.	                    "    <tr>\n" +  
25.	                    "    <th>id</th><th>温度</th><th>湿度</th><th>时间</th>\n" +  
26.	                    "    </tr>");  
27.	            resultSet.next();  
28.	            int id1 = resultSet.getInt("id");  
29.	            String temp = resultSet.getString("temperature");  
30.	            String humid = resultSet.getString("humidity");  
31.	            String time1 = resultSet.getString("create_time");  
32.	            out.println( "<tr>\n" +  
33.	                    " <td>"+id1+"</td><td>"+temp+"</td><td>"+humid+"</td><td>"+time1+"</td>\n" +  
34.	                    " </tr>");  
35.	            out.println("</table>");  
36.	  
37.	    }catch (SQLException sqlException){  
38.	        out.println("<h1 align=center>加载失败</h1>");  
39.	        out.println(sqlException);  
40.	    }  

(2)重定向界面1,光照的历史数据

1.	try {  
2.	        Class.forName("com.mysql.jdbc.Driver");  
3.	        connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/zigbee1?characterEncoding=utf-8","root","111111");  
4.	        String sql = "select * from lightstrength";  
5.	        statement = connection.createStatement();  
6.	        int n = 0;  
7.	        resultSet = statement.executeQuery(sql);  
8.	        out.println("<table align=\"center\" border=\"2px\">\n" +  
9.	                "    <tr>\n" +  
10.	                "    <th>id</th><th>光照强度</th><th>时间</th>\n" +  
11.	                "    </tr>");  
12.	        while (resultSet.next()) {  
13.	            n++;  
14.	            int id = resultSet.getInt("id");  
15.	            String light = resultSet.getString("light");  
16.	            String time = resultSet.getString("create_time");  
17.	            out.println( "<tr>\n" +  
18.	                    " <td>"+id+"</td><td>"+light+"</td><td>"+time+"</td>\n" +  
19.	                    " </tr>");  
20.	        }  
21.	        out.println("</table>");  
22.	    }catch (SQLException sqlException){  
23.	        out.println("<h1 align=center>加载失败</h1>");  
24.	        out.println(sqlException);  
25.	    }  

(3)重定向界面2,温湿度的历史数据

1.	try {  
2.	        Class.forName("com.mysql.jdbc.Driver");  
3.	        connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/zigbee1?characterEncoding=utf-8","root","111111");  
4.	  
5.	        String sql = "select * from zigbee_receive_data";  
6.	        statement = connection.createStatement();  
7.	        int n = 0;  
8.	/*         preparedStatement.setString(1, "%"+name1+"%"); */  
9.	        resultSet = statement.executeQuery(sql);  
10.	        out.println("<table align=\"center\" border=\"2px\">\n" +  
11.	                "    <tr>\n" +  
12.	                "    <th>id</th><th>温度</th><th>湿度</th><th>时间</th>\n" +  
13.	                "    </tr>");  
14.	        while (resultSet.next()) {  
15.	            n++;  
16.	            int id = resultSet.getInt("id");  
17.	            String temp = resultSet.getString("temperature");  
18.	            String humid = resultSet.getString("humidity");  
19.	            String time = resultSet.getString("create_time");  
20.	            out.println( "<tr>\n" +  
21.	                    " <td>"+id+"</td><td>"+temp+"</td><td>"+humid+"</td><td>"+time+"</td>\n" +  
22.	                    " </tr>");  
23.	        }  
24.	        out.println("</table>");  
25.	    }catch (SQLException sqlException){  
26.	        out.println("<h1 align=center>加载失败</h1>");  
27.	        out.println(sqlException);  
28.	    }  

3.界面设计

(1)选择软件工具,建立工程。

(2)设计显示界面。

硬件设备

图5 传感器连接

端口连接

图6 在IAR上烧写传感器程序

图7 串口连接助手接收数据

图8 PC端可接收到传感器数据

数据库设计界面

图9 数据库建表属性

图10 数据库光照表

图11 数据库温湿度表

后端代码实现

图12 后端服务器接收数据

图13 后端服务器界面

前端设计界面


图14 查看数据界面


图15 当前光照强度界面


图16 当前温湿度界面

四.系统说明

本系统搭建了一个温湿度的采集显示环境,能够采集周围环境中的温度、湿度值,并且实时在PC机上显示。PC机实时显示界面如图:


图17 PC机实时显示界面

环境监测系统是一种用于监测周围环境参数的系统,其中包括温度、湿度等参数。下面是环境监测系统的详细说明:s

1. 硬件设备

该系统需要使用以下硬件设备:

- 温湿度传感器:用于采集周围环境中的温度和湿度数据。可以使用数字温湿度传感器,例如SHT10等。

- 微处理器或单板计算机:用于读取传感器数据并将其发送到PC机。

- 串口转USB模块:用于将微处理器或单板计算机的串口信号转换为USB信号,以便将数据发送到PC机。

- PC机:用于接收和显示传感器数据。PC机可以运行Windows、Linux等操作系统。

2. 软件程序

该系统需要使用以下软件程序:

  1. 微处理器或单板计算机的固件程序:用于读取传感器数据并将其发送到PC机。可以使用C、C++、Python等编程语言编写程序。
  2. PC机上的数据接收程序:用于接收和解析来自微处理器或单板计算机的数据,并将其显示在PC机上。可以使用C、C++、Python等编程语言编写程序。

3. 系统实现步骤

  1. 以下是实现该系统的一般步骤:
  2. 连接温湿度传感器到微处理器或单板计算机上。传感器通常需要一个电源和数据线连接。
  3. 编写微处理器或单板计算机的固件程序,以读取传感器数据并将其发送到PC机。程序应该能够周期性地读取传感器数据,并将数据以可读的格式发送到PC机。
  4. 在PC机上编写数据接收程序,以接收和解析来自微处理器或单板计算机的数据,并将其显示在PC机上。程序可以在命令行终端、GUI界面或Web界面上显示数据。
  5. 将微处理器或单板计算机连接到PC机上。可以使用串口转USB模块将串口信号转换为USB信号,以便将数据发送到PC机。
  6. 启动数据接收程序并开始监测环境参数。如果一切正常,您应该能够在PC机上看到实时的温度和湿度数据。

五.设计总结

系统采用SHT10单片数字温湿度传感器将温湿度采集集成在一起,数据的读取要采用时序控制来进行。采集变量的实时显示由编制界面来完成。

图18 编译界面

在编写界面时,可以考虑使用一个微控制器或单板计算机来读取传感器数据并将其显示在一个显示器上。可以使用各种编程语言和开发工具来编写界面,例如C++、Python、Arduino IDE等。

以下是一些需要考虑的步骤:

1. 连接SHT10传感器到微控制器或单板计算机上。传感器通常需要一个电源和数据线连接。

2. 编写代码来读取传感器数据。可以使用SHT10传感器的数据手册来了解如何采集数据和解码数据。

3. 将读取的数据显示在一个显示器上。您可以使用LCD显示器、LED灯或其他显示设备来显示数据。

4. 对于实时数据的更新,可以使用一个定时器或中断来定期读取传感器数据并更新显示。

5. 考虑添加一些用户界面元素,例如按钮或滑块,以便用户可以控制数据采集和显示。

心得体会:

本次实验我们使用了WSN 2530CC的温湿度传感器和光敏传感器,在实验过程中,我们习得了如何用IAR软件烧写传感器和协调器、串口调试工具收发数据、用Java写接收数据的接口、如何把接收到的数据存储到数据库中以及用js从数据库调出数据编写前端页面等。

  1. Zigbee通信原理

Zigbee无线通信,需要高频的载波来提供发射效率。Zigbee模块之间要想正常的收发数据,接收模块必须把接收频率和发射模块的载波频率设置一致。

1)在Zigbee的无线局域网中,节点按照网络里面的功能划分为:协调器、路由器(本实验并没有用到路由,但是路由也是值得我们去学习的)、终端节点。说一个模块到底是协调器、路由器还是终端,前提是它必须在一个Zigbee无线局域网里,如果它还没有入网,那么它仅仅是一个下载了响应功能代码的模块而已。

下载了路由器和终端代码的模块,上电后第一件事是去寻找网络,请求加入;网络是不会平白无故产生的,所以创建网络这个工作由下载了协调器代码的模块来完成,下载协调器代码的模块上电的第一件事是去创建网络。任何一个网络,第一个节点一定是该网络的协调器,一个网络里有且仅有一个协调器。

2)协调器

协调器:创建一个无线局域网络的模块叫做协调器。协调器在创建网络之后,协调器的地位和路由器将是一样的,都是负责把终端的消息发送出去。

3)其他模块入网的过程

任何一个Zigbee模块要加入到某个网络,一定要一个处于该网络里的节点作为介绍人,并且这个介绍人不能是终端节点。

在节点加入到网络以后,介绍人节点和被介绍加入的节点互为父子关系,介绍人节点是被介绍加入节点的父节点,被介绍加入节点是介绍节点的子节点。当被加入节点有多个介绍人可以选择加入的时候,根据相对于被加入节点的信号强度等一些其他的参数,选择最佳的介绍人节点加入。Zigbee网络组建以后,网络里的节点可以进行相互通信,数据通信的方式有4种:单播、广播、组播、绑定。

4)各个功能型模块路由器、终端、协调器入网前的操作

① 路由器节点

路由器在加入局域网络之前,会一直发送信标请求帧,信标请求帧的作用是,让在它附近的所有具备介绍人资格的节点,都回复信标帧,这些返回的信标帧被这个想要加入的无线模块拿到,路由器模块通过这些信标帧,选出最佳介绍人节点,请求加入。

② 终端节点

终端节点在入网前的行为和下载了路由器代码模块的入网前行为是一样的。

③ 协调器节点

协调器在创建局域网络之前,会发送了一帧信标请求帧,发送这一帧也会得到周围具备介绍人资格的节点回复信标帧,但是协调器拿到这些信标帧,用来判断周围的环境情况,为创建网络做准备。当协调器创建网络成功以后,就会发送一个数据帧,这个帧里面可以看到协调器的地址0x0000、PANID(创建的网络ID),可以把这个帧叫做网络连接状态帧。

  1. IAR烧写

    安装集成开发环境: IAR。

    安装仿真器“SmartRF4EB”的驱动程序。

    安装代码烧写工具: Setup_SmartRF_Programmer_1.10.2。

    安装 TI 的 Zigbee 协议栈: ZStack-CC2530-2.5.1a。

  2. 串口调试工具的使用注意事项

    首先根据串口发过来的信息选择波特率,这个波特率根据实际需要选择,要保证收发一致,否则可能收不到数据,有的时候可以收到,但是都是乱码

    根据传输协议,设置数据位,校验位,停止位,这三个也需要与发送端保持一致,一般来说都是默认设置8-N-1

    连接好硬件后,选择传输端口,对应电脑上的USB口

    设置数据收发模式,根据实际需要选择

    点击“运行”,即可收发数据包

  3. 如何用java接收传感器数据(使用到了RXTXcomm)以及如何把接收到的数据存储到本地的数据库中

    RXTXcomm.jar提供了通讯用的java API,win32com.dll提供了供RXTXcomm.jar调用的本地驱动接口,javaxm.properties是这个驱动的类配置文件

    获取数据的步骤:

    1. 获取当前所有可用的串口信息、遍历所有的串口信息
      1. 解析端口类型的
        1. 通过 CommPortIdentifier 类对象,打开端口,并获取到连接对象CommPort类的实例
        2. 通过设置监听器来处理接收数据,监听器必须实现SerialPortEventListener接口,并通过serialPort.addEventListener(this);来注册监听器
        3. 接收到数据后先把数据转化成字符串,再转化成浮点数,对温湿度进行换算,转化称为十进制有效数据
        4. 连接mysql数据库,添加JDBC驱动,连接数据库,用SQL语句把接收到的有效数据传进去
  4. 如何用js连接数据库,提取数据

    1. 首先要安装好Tomcat 本次我们使用的Tomcat 7

      1. 初始化数据库连接信息,像下面这样

      const conn = mysql.createConnection({<!-- -->

      host:‘localhost’, // 主机名 (服务器地址)

      user:‘root’, //用户名

      password:‘root’, // 密码

      database:‘数据库名字’, // 写上自己要连接的数据库名字

      })

      1.  建立连接,执行sql语句
      2.  同时为了满足用户点击按钮跳转操作,我们设置了重定向页面,满足多个不同信息的分类显示。
      

以上是我们在编写程序代码中所要解决的一些问题,但在提交过程中我们还了解到作为开发人员,不能只考虑实现的功能,也要在乎界面的赶紧整洁,满足用户的各项需求,比如在后端的运行窗口中,所设计的窗口较小,会使得用户看起来比较费劲,比如窗口的组件布局,由于没有固定,导致排列不够美观,比如前端界面,提取的数据不应该只以表格的方式呈现,会使得不够直观,如果能使用曲线图,将会使得更符合用户的使用习惯,并且更加直观简洁。

同时在提交过程中,我还发现了,为了提高界面的流畅性和美观性,市面流行的Echarts组件能够很好的满足我们所制作的Javaweb项目:

简单记录一下我对Echarts目前的了解吧:ECharts是一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器,底层依赖矢量图形库 ZRender,提供直观,交互丰富,可高度个性化定制的数据可视化图表:

1,ECharts 属于开源软件,并且我们提供了非常炫酷的图形界面,特色是地图,另外还提供了柱状图、折线图、饼图、气泡图及四象限图等;

2,ECharts 使用简单,在官网中为我们封装了 JS,只要会引用就会得到完美的展示效果;

3,ECharts 种类多,ECharts 实现简单,各类图形都有;相应的模板,还有丰富的 API 及文档说明,非常详细;

4,ECharts 兼容性好,基于HTML5,有着良好的动画渲染效果;

这也是我们项目的改进方向,虽然我们的项目还有很多不足,但是在这个过程中所学的知识是很珍贵的。

六.附录

源程序文件名清单

TempAndHum.h //传感器程序

Coordinator.h //协调器程序

ContinueckRead.java //测温湿度和光照程序

light.jsp //查询光照界面

Temperature.jsp //查询温湿度界面

Redirect.jsp //功能界面

七.问题分析

1.如何在IDEA里面只运行一个java文件,而不是编译运行整个项目

(1)点击Edit Configurations…

(2)在界面最下方的Before launch:Activate tool window中,点击build,然后点击上面的-,不让它编译整个项目即可。

(3)运行的时候直接点run xxx.main就可以运行了。

2.IDEA开启tomcat后,不能访问localhost:8080页面的解决方法

(1)在IDEA主界面,点击一下绿色三角形左边的框框,选择Edit Configurations,在弹出的配置面板上找到Tomcat Server并点击。

(2)点击右边的加号,会有一个Add New Configuration的弹出框。我们将鼠标移到Tomcat Server上,然后选择Local选项,这里我们是将项目部署到本地服务器上。然后给服务任意取个名称,然后配置一下服务器,以及访问的网址URL。

(3)点击右边configure,配置本地Tomcat-Home

点击Deployment,点击加号,点击Artifact,选择当前应用。

接着点击加号,点击external source,选中tomcat解压路径的ROOT文件夹,完成Tomcat首页的部署

点击小铅笔,点击Output Layout下面的加号,点击Derectory Content 配置tomcat安装目录下的 webapps,一路Apply-OK即可。

点击绿色三角形运行

3.于使用IDEA编写jsp代码出现Cannot resolve method‘setCharacterEncoding(java.lang.String)’如何解决

造成这个问题的原因其实就是没把tomcat–>lib里的一些所必须的jar包导入

  1. 首先左上角file–>Project Structure
    1. 选择左边列表的Modules,点击右边+号,选择JARs or Directories
    2. 找到tomcat安装路径下lib文件夹里选择jsp-api.jar,servlet-api.jar,tomcat-api.jar(tomcat安装路径参考自己的),点击OK
    3. 可以看到刚刚选择的三个jar包已经添加进来了,继续点击Apply–>OK
    4. 问题成功解决

3.JAVA的延时函数使用

在Java中有时候需要使程序暂停一点时间,称为延时。普通延时用Thread.sleep(int)方法,这很简单。把它将当前线程挂起指定的毫秒数。如

try

{

Thread.sleep(1000);//单位:毫秒

} catch (Exception e) {

}

注意:Thread.sleep(int)不能直接用,要做异常处理,try{}catch{}.

在这里需要解释一下线程沉睡的时间。sleep()方法并不能够让程序"严格"的沉睡指定的时间。例如当使用5000作为sleep()方法的参数时,线 程可能在实际被挂起5000.001毫秒后才会继续运行。当然,对于一般的应用程序来说,sleep()方法对时间控制的精度足够了。

但是如果要使用精确延时,最好使用Timer类:

Timer timer=new Timer();//实例化Timer类

timer.schedule(new TimerTask(){

public void run(){

System.out.println("退出");

this.cancel();}},500);//五百毫秒

这种延时比sleep精确。上述延时方法只运行一次,如果需要运行多次, 使用timer.schedule(new MyTask(), 1000, 2000); 则每间隔2秒执行MyTask()

  1. IDEA jsp无法识别response.setCharacterEncoding()等解决方法

需要在Module添加Tomcat,点击绿色箭头指向的加号,点击第二个library,然后添加Tomcat即可。

  1. tomcat7启动报错:java.lang.NoSuchMethodException: org.apache.catalina.deploy.WebXml addFilter如何解决

在tomcat目录下conf下的context.xml中添加<Loader delegate=“true”/> 属性。

经过查询资料显示,该属性含义如下 :

True,表示tomcat将遵循JVM的delegate机制,即一个WebAppClassLoader在加载类文件时,会先递交给SharedClassLoader加载,SharedClassLoader无法加载成功,会继续向自己的父类委托,一直到BootstarpClassLoader,如果都没有加载成功,则最后由WebAppClassLoader自己进行加载。

False,表示将不遵循这个delegate机制,即WebAppClassLoader在加载类文件时,会优先自己尝试加载,如果加载失败,才会沿着继承链,依次委托父类加载。

  1. IDEA报错org.apache.catalina.deploy.WebXml addServlet如何解决
  2. 在IDEA主界面,点击一下run左边的框框,选择Edit Configurations,在弹出的配置面板上找到Tomcat Server并点击。
  3. 点击tomcat server下面的run,然后点击右边configure
  4. 发现在classes中多出一个servle包。删掉即可
  5. 怎样实现温湿度十六进制数据包转换,转换的数字再通过JTextFiled显示

(1)解析数据包:将接收到的十六进制数据包转换为字节数组,然后根据传感器协议的规定,提取出温度和湿度数据的字节。

(2)将字节转换为实际数值:根据传感器协议规定的数据格式,将温度和湿度数据的字节转换为实际的温度和湿度值。例如,如果传感器协议规定温度数据是一个有符号的16位整数,湿度数据是一个无符号的8位整数,则需要将字节转换为相应的整数类型,并应用适当的位运算和缩放因子。

(3)在JTextField中显示数值:使用JTextField.setText()方法将实际的温度和湿度值以文本形式显示在JTextField中。

以下是一个示例代码,它假设温度数据占用数据包的第1和第2个字节,湿度数据占用数据包的第3个字节,数据格式为有符号16位整数和无符号8位整数:

\`\`\`java

// 假设 dataPacket 是接收到的十六进制数据包

byte[] data = hexStringToByteArray(dataPacket);

// 解析温度和湿度数据

int temperature = (data[0] \<\< 8) \| (data[1] & 0xff); // 有符号16位整数

int humidity = data[2] & 0xff; // 无符号8位整数

// 计算实际温度和湿度值

float realTemperature = (float) temperature / 100; // 假设缩放因子为 100

float realHumidity = (float) humidity;

// 在 JTextField 中显示数值

textField.setText("Temperature: " + realTemperature + "°C, Humidity: " + realHumidity + "%");

\`\`\`

7.如何实现温湿度的判断决策

以下是一个简单的示例,假设您需要判断当前的温湿度是否适宜人类居住:

(1)定义规则:根据气象学的相关标准,通常认为温度在20-25°C之间,相对湿度在40-60%之间适宜人类居住。

(2)获取当前温湿度值:可以使用温湿度传感器获取实时温湿度值。

(3)判断是否符合规则:比较当前的温湿度值是否在适宜范围内。如果符合规则,则可以输出“当前温湿度适宜人类居住”等信息。如果不符合规则,则可以输出“当前温湿度不适宜人类居住,请采取相应的措施”等信息。

以下是一个示例代码,假设当前的温湿度值存储在两个变量中:temperature和humidity:

\`\`\`java

// 定义适宜人类居住的温湿度范围

float minTemperature = 20;

float maxTemperature = 25;

float minHumidity = 40;

float maxHumidity = 60;

// 获取当前的温湿度值

float currentTemperature = temperature; // 假设已经获取到实时温度值

float currentHumidity = humidity; // 假设已经获取到实时湿度值

// 判断是否符合规则

if (currentTemperature \>= minTemperature && currentTemperature \<= maxTemperature

&& currentHumidity \>= minHumidity && currentHumidity \<= maxHumidity) {

System.out.println("当前温湿度适宜人类居住");

} else {

System.out.println("当前温湿度不适宜人类居住,请采取相应的措施");

// 在此可以执行相应的操作,如打开空调或加湿器等

}

\`\`\`

7.存数据库的格式是怎样的

以下是一个示例,假设需要存储温湿度数据到MySQL数据库中:

(1)创建数据库表:可以使用SQL命令创建一个名为“temperature_humidity”的表,包含以下字段:

\- id:整数类型,作为主键

\- temperature:浮点数类型,表示温度值

\- humidity:浮点数类型,表示湿度值

\- timestamp:时间戳类型,表示记录时间

\`\`\`sql

CREATE TABLE temperature_humidity (

id INT NOT NULL AUTO_INCREMENT,

temperature FLOAT NOT NULL,

humidity FLOAT NOT NULL,

timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,

PRIMARY KEY (id)

);

\`\`\`

(2)将温湿度数据保存到数据库:在应用程序中,可以使用相应的数据库驱动程序连接到MySQL数据库,并使用SQL命令将温湿度数据插入到“temperature_humidity”表中。

以下是一个示例代码,假设当前的温湿度值存储在两个变量中:temperature和humidity:

```java

// 假设已经获取到实时温湿度值
float currentTemperature = temperature;
float currentHumidity = humidity;

// 连接到 MySQL 数据库
String url = "jdbc:mysql://localhost:3306/mydatabase";
String user = "myuser";
String password = "mypassword";
Connection conn = DriverManager.getConnection(url, user, password);

// 插入温湿度数据到数据库
String sql = "INSERT INTO temperature_humidity (temperature, humidity) VALUES (?, ?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setFloat(1, currentTemperature);
pstmt.setFloat(2, currentHumidity);
pstmt.executeUpdate();

// 关闭数据库连接
pstmt.close();
conn.close();

八.系统可改进

实际人机交互界面未考虑用户舒适度,界面过小,不易查看与操作;

改进措施:

1、考虑用户舒适度:在设计界面时,要考虑用户的舒适度,如字体大小、颜色、背景色等要选择合适的,确保用户能够轻松地辨认和阅读界面信息,同时也要避免界面过于繁琐和复杂。

2、调整界面大小:根据用户的需求和使用环境,可以调整界面的大小,使其满足用户查看和操作的需求。如果是在移动设备上使用,可以通过放大或缩小手势来调整界面大小。

3、增加交互元素:为了方便用户操作,可以增加一些交互元素,如按钮、滑块、菜单等,使用户能够更轻松地进行操作。

4、提供用户个性化设置:为了满足不同用户的需求,可以提供个性化设置功能,让用户自由选择界面的字体大小、颜色、背景色等,以便更好地适应用户的个人喜好和视力水平。

5、进行用户测试:为了确保界面的易用性和舒适性,可以进行用户测试,收集用户的反馈和建议,进一步改进界面设计,提高用户的满意度和使用体验。

综上所述,改进人机交互界面需要从用户的角度出发,以用户的需求为中心,注重用户体验和舒适度,不断优化和改进设计,提高界面的易用性和可接受性。

数据库信息更新过快,未考虑实际情况,无法为管理人员提供有效信息;

改进措施:

1、调整更新频率:根据实际情况,适当调整数据库信息更新的频率,避免过于频繁地进行更新,以免造成管理人员信息过载的情况。比如每分钟提取一条数据特征更新到数据库。

2、设计筛选机制:针对不同的管理人员角色和需求,设计筛选机制,让他们能够根据自己的需求和关注点,筛选出有用的信息,提高信息的准确性和可用性。

3、进行数据分析:对数据库中的信息进行分析,提取有用的信息,形成可视化的图表和报表,以便管理人员更好地了解和应对实际情况。

4、加强系统监控:在系统中加入监控机制,对数据库信息更新的频率和质量进行监控和预警,及时发现和解决问题,保证数据库信息的质量和准确性。

前端界面刷新速度过高,不易于用户查看了解;

改进措施:

1、调整刷新频率:根据实际情况和用户需求,适当调整前端界面的刷新频率,使刷新速度与用户查看信息的需要相匹配,避免刷新速度过快导致用户信息过载。

2、加入滚动条或分页机制:对于较长的信息列表或数据表格,可以加入滚动条或分页机制,让用户可以自主选择查看的信息范围,不需要一次性加载全部信息。

3、增加信息提示:对于重要的信息更新,可以增加信息提示,让用户可以及时了解到相关信息的更新情况,避免用户错过重要信息。

4、优化界面设计:在前端界面设计时,尽量减少不必要的动画效果和闪烁,避免干扰用户的视线,同时优化界面设计,让用户可以更轻松地查看和了解信息。

5、提供数据查询功能:为了方便用户查找和筛选信息,可以提供数据查询功能,让用户可以自主选择和筛选信息,以便更好地了解和分析相关信息。

数据库信息存储时间短,无法追溯一定时间前的环境状态。

改进措施:

1、增加数据存储容量:扩大数据库存储容量,增加数据存储时间,以便更好地追溯历史环境状态信息。

2、设置数据备份机制:设置数据备份机制,定期备份历史数据,以便在需要时能够查看和恢复历史数据。

3、设计历史数据查询功能:增加历史数据查询功能,让用户可以查询一定时间范围内的历史数据,以便更好地了解历史环境状态。

4、进行数据分析和建模:对历史数据进行分析和建模,形成历史环境状态模型,以便更好地了解历史环境状态的变化趋势和特点。

5、进行数据挖掘和预测:通过对历史数据的挖掘和分析,预测未来环境状态的变化趋势,为环境管理和决策提供决策支持和建议。

本文标签: 工程 专业 太理物