2024西电A测:湿度测控仿真系统

写在前面:

RT,本文结合往届学长以及本人采用python写成的GUI可视化实现一个PC上位机的远程湿度检测控制系统。对往届学长西电陈奕迅和flovst表示感谢,为我们铺路。

题目:

使用学校提供的RHMeasSyst.pdsprj半成品来完成PC上位机远程湿度检测控制系统。

软件环境:推荐采用 Proteus 8.9 SP2 及以上仿真软件, Arduino IDE ,虚拟串口
驱动软件 Virtual Serial Port Driver VSPD )。
系统框图如下:
功能: Arduino UNO Atmega328P )通过串行接口组件与上位机 PC 进行双向
通信, PC 上位机软件向 Arduino UNO 发送学生自己的学号, Arduino UNO 收到
后在 LCD 上显示学生的学号,并且向 PC 机发送当前的湿度值。 PC 上位机软件
显示收到的湿度值。

软件下载链接:

Proteus8.9 下载与安装教程_proteus下载-CSDN博客

虚拟串口 VSPD 的使用_vspd使用教程-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,出国留学的同学们科研路上走得更远!

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不是很爱摆烂的小李

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值