写在前面:
RT,本文结合往届学长以及本人采用python写成的GUI可视化实现一个PC上位机的远程湿度检测控制系统。对往届学长西电陈奕迅和flovst表示感谢,为我们铺路。
题目:
使用学校提供的RHMeasSyst.pdsprj半成品来完成PC上位机远程湿度检测控制系统。

软件下载链接:
Proteus8.9 下载与安装教程_proteus下载-CSDN博客
百度网盘 请输入提取码 7de8
https://projecthub.arduino.cc/arcaegecengiz/using-dht11-12f621 这个DHT11传感器的链接在github上可以找到
下载里面的压缩包即可,后续不需要解压。
配置流程:
1.创建串口:
打开你的Virtual Serial Port Driver 7.2也就是VSPD
选择两个COM成为一对虚拟的串口 ,本人创建的是COM3和COM4
2.验证串口通信:
再打开两个XCOM V2.0,如下配置,正确的话双方即可以互相通信。
测试好之后关闭其中一个端口,如本人关闭COM3,保持COM4开启即可。
3.IDE编辑
打开 Arduino IDE,首先在IDE的左上角点击项目->加载库->添加.zip库,选择之前下载的 DHT11 库的.zip文件。同时再点击文件->首选项,将显示详细输出后的编译、上传选上。
IDE源码:
# include <Wire.h>
# include <dht11.h> // DHT11库
# include <LiquidCrystal.h> // LCD控制相关库
// 定义引脚
# define DHT11PIN 6
# define EMPIN 7
LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // 初始化LCD
dht11 DHT11;
String str = ""; // 定义字符串str,接收学号
int length_, last = 0;
int setHumidity, realHumidity = 0;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600); // 初始化串口,设置波特率为9600
lcd.begin(16, 2);
pinMode(EMPIN, OUTPUT); // 设置连接直流电机引脚工作模式
}
void loop() {
// put your main code here, to run repeatedly:
DHT11.read(DHT11PIN);
realHumidity = (int)DHT11.humidity;
lcd.print("ID:");
if (Serial.available() > 0) { // 串口接收到数据
while (Serial.available() > 0) {
str += (char)Serial.read();
delay(10);
}
lcd.println(str);
length_ = str.length();
last = str.substring(length_ - 3, length_ - 2).toInt(); // 取末尾数字
setHumidity = 30 + last;
str = "";
length_ = 0;
last = 0;
}
lcd.setCursor(0, 1); // 将光标定位在第0列,第1行
lcd.print("RH:");
lcd.print(realHumidity);
lcd.println("%");
lcd.home(); // 光标返回左上角
Serial.print("Humidity:");
Serial.print(realHumidity);
Serial.println("%");
if (realHumidity <= setHumidity) {
digitalWrite(EMPIN, HIGH); // 电机转动
} else {
digitalWrite(EMPIN, LOW);
}
delay(1000);
}
点击之后等待即可,出现如下就说明成功了。
找到 .ino.hex 文件,这里推荐使用everything搜索
4.仿真
打开半成品RHMeasSyst.pdsprj文件
双击仿真图中左上角的芯片(就是最大的那个),把其中的Program File 后的文件地址改为上面复制的 .ino.hex 文件的地址,点击确定。
再点击这个
配置如下:
开始左下角按钮运行,显示湿度
其中这两个按钮可以上下调整湿度的大小。
使用XCOM测试,选择COM4,可以发现可以检测到湿度79%的值。
发送内容,如12306,可以在液晶屏上显示。
现在需要代替XCOM,自己做一个可视化GUI程序。
5.代替XCOM
本人使用python实现了XCOM的代替
效果如图,可以发现成功替代。前提是之前的XCOM的COM4得关闭
源码如下: 需要pip install pyserial安装此库来完整运行代码
import tkinter as tk
from tkinter import ttk
from threading import Thread
try:
import serial
import serial.tools.list_ports
pyserial_installed = True
except ImportError:
pyserial_installed = False
class SerialGUI:
def __init__(self, root):
self.root = root
self.root.title("可视化")
# 串口相关
self.serial_port = None
self.is_open = False
# 检查 pyserial 是否安装
if not pyserial_installed:
self.text_area = tk.Text(root, height=15, width=50)
self.text_area.grid(row=0, column=0, columnspan=2, padx=5, pady=5)
self.text_area.insert(tk.END, "pyserial 库未安装,请运行以下命令安装:\n\npip install pyserial")
return # 停止初始化 GUI
# 串口选择框
self.port_label = tk.Label(root, text="串口选择")
self.port_label.grid(row=0, column=0, padx=5, pady=5)
self.port_combo = ttk.Combobox(root, values=self.get_serial_ports())
self.port_combo.grid(row=0, column=1, padx=5, pady=5)
# 波特率
self.baud_label = tk.Label(root, text="波特率")
self.baud_label.grid(row=1, column=0, padx=5, pady=5)
self.baud_combo = ttk.Combobox(root, values=["9600", "115200"], state="readonly")
self.baud_combo.set("9600")
self.baud_combo.grid(row=1, column=1, padx=5, pady=5)
# 打开/关闭串口按钮
self.toggle_btn = tk.Button(root, text="打开串口", command=self.toggle_serial)
self.toggle_btn.grid(row=2, column=0, columnspan=2, padx=5, pady=5)
# 数据显示区
self.text_area = tk.Text(root, height=15, width=50)
self.text_area.grid(row=3, column=0, columnspan=2, padx=5, pady=5)
# 发送数据区
self.entry = tk.Entry(root)
self.entry.grid(row=4, column=0, padx=5, pady=5)
self.send_btn = tk.Button(root, text="发送", command=self.send_data)
self.send_btn.grid(row=4, column=1, padx=5, pady=5)
def get_serial_ports(self):
"""获取可用串口"""
if pyserial_installed:
ports = serial.tools.list_ports.comports()
return [port.device for port in ports]
return []
def toggle_serial(self):
"""打开或关闭串口"""
if self.is_open:
self.close_serial()
else:
self.open_serial()
def open_serial(self):
"""打开串口"""
port = self.port_combo.get()
baudrate = self.baud_combo.get()
try:
self.serial_port = serial.Serial(port, baudrate, timeout=1)
self.is_open = True
self.toggle_btn.config(text="关闭串口")
self.start_reading()
except Exception as e:
self.text_area.insert(tk.END, f"无法打开串口: {e}\n")
def close_serial(self):
"""关闭串口"""
if self.serial_port:
self.serial_port.close()
self.is_open = False
self.toggle_btn.config(text="打开串口")
def start_reading(self):
"""启动串口读取线程"""
self.read_thread = Thread(target=self.read_data)
self.read_thread.daemon = True
self.read_thread.start()
def read_data(self):
"""从串口读取数据"""
while self.is_open:
try:
data = self.serial_port.readline().decode('utf-8')
if data:
self.text_area.insert(tk.END, data)
except Exception as e:
self.text_area.insert(tk.END, f"读取错误: {e}\n")
def send_data(self):
"""发送数据"""
data = self.entry.get()
if self.serial_port and self.is_open:
self.serial_port.write(data.encode('utf-8'))
self.text_area.insert(tk.END, f"发送: {data}\n")
else:
self.text_area.insert(tk.END, "串口未打开\n")
# 启动GUI
if __name__ == "__main__":
root = tk.Tk()
gui = SerialGUI(root)
root.mainloop()
完美收官!
写在最后
在西电的第七学期,我深深明白了学长学姐们贡献和荫蔽的重要性。谢谢你们!
今日是2024年9月25日,也希望保研的同学们找到满意的导师,考研的同学们安心备考,考出好成绩,找工作的同学们找到心仪的offer,出国留学的同学们科研路上走得更远!