python单片机串口采集温湿度并录入数据库

一、环境配置及软硬件

  • 环境配置及软件
  1. eclipse
  2. Keil5
  3. mysql
  4. Navicat
  5. Eclipse配置python开发环境

相关参考:
Eclipse下配置python环境.
pip升级安装难题.
windows环境下安装pymysql.
Python MySQL - mysql-connector 驱动.
(本人配置时主要参考了这些,以外的自身以前配置过,其他的软件安装过程请自行搜索。)

  • 硬件
  1. STM32F103系列单片机(野火mini)
  2. 温湿度传感器AHT20
  3. 杜邦线

二、代码

  • 单片机上要烧入的温湿度模块main.c代码:
#include "led.h"
#include "usart.h"
#include "temhum.h"

 int main(void)
 {
    
    	 	
    u32 CT_data[2]={
    
    0};
    volatile float  hum=0,tem=0;   
    int q=0;		
     
    delay_init();	    	 //延时函数初始化	  
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    uart_init(115200);	 //串口初始化为115200
    LED_Init();			     //LED端口初始化
    temphum_init();     //ATH20初始化    
	
	while(1)
	{
    
    
        AHT20_Read_CTdata(CT_data);       //不经过CRC校验,直接读取AHT20的温度和湿度数据 

        hum = CT_data[0]*100*10/1024/1024;  //计算得到湿度值(放大了10倍)
        tem = CT_data[1]*200*10/1024/1024-500;//计算得到温度值(放大了10倍)
        if(q%2==0)
		  printf("%.1f%",(hum/10));
		if(q%2!=0)
          printf("%.1f",(tem/10));
        
        //延时2s,LED闪烁提示串口发送状态
        LED=0;
        delay_ms(1000);
        LED=1;
        delay_ms(1000);
		    q=q+1;
	 }
}

这里单片机主要先输出湿度再输出温度只输出数值,且分开输出避免读取错误。

  • eclipse上的python代码:
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import serial
import serial.tools.list_ports
import pymysql # 导入pymysql包

class Communication():

    #初始化
    def __init__(self,com,bps,timeout):
        self.port = com
        self.bps = bps
        self.timeout =timeout
        global Ret
        try:
            # 打开串口,并得到串口对象
             self.main_engine= serial.Serial(self.port,self.bps,timeout=self.timeout)
            # 判断是否打开成功
             if (self.main_engine.is_open):
               Ret = True
        except Exception as e:
            print("---异常---:", e)

    # 打印设备基本信息
    def Print_Name(self):
        print(self.main_engine.name) #设备名字
        print(self.main_engine.port)#读或者写端口
        print(self.main_engine.baudrate)#波特率
        print(self.main_engine.bytesize)#字节大小
        print(self.main_engine.parity)#校验位
        print(self.main_engine.stopbits)#停止位
        print(self.main_engine.timeout)#读超时设置
        print(self.main_engine.writeTimeout)#写超时
        print(self.main_engine.xonxoff)#软件流控
        print(self.main_engine.rtscts)#软件流控
        print(self.main_engine.dsrdtr)#硬件流控
        print(self.main_engine.interCharTimeout)#字符间隔超时

    #打开串口
    def Open_Engine(self):
        self.main_engine.open()

    #关闭串口
    def Close_Engine(self):
        self.main_engine.close()
        print(self.main_engine.is_open)  # 检验串口是否打开

    # 打印可用串口列表
    @staticmethod
    def Print_Used_Com():
        port_list = list(serial.tools.list_ports.comports())
        print(port_list)





    #接收指定大小的数据
    #从串口读size个字节。如果指定超时,则可能在超时后返回较少的字节;如果没有指定超时,则会一直等到收完指定的字节数。
    def Read_Size(self,size):
        return self.main_engine.read(size=size)

    #接收一行数据
    # 使用readline()时应该注意:打开串口时应该指定超时,否则如果串口没有收到新行,则会一直等待。
    # 如果没有超时,readline会报异常。
    def Read_Line(self):
        return self.main_engine.readline()

    #发数据
    def Send_data(self,data):
        self.main_engine.write(data)

    #更多示例
    # self.main_engine.write(chr(0x06).encode("utf-8"))  # 十六制发送一个数据
    # print(self.main_engine.read().hex())  #  # 十六进制的读取读一个字节
    # print(self.main_engine.read())#读一个字节
    # print(self.main_engine.read(10).decode("gbk"))#读十个字节
    # print(self.main_engine.readline().decode("gbk"))#读一行
    # print(self.main_engine.readlines())#读取多行,返回列表,必须匹配超时(timeout)使用
    # print(self.main_engine.in_waiting)#获取输入缓冲区的剩余字节数
    # print(self.main_engine.out_waiting)#获取输出缓冲区的字节数
    # print(self.main_engine.readall())#读取全部字符。

    #接收数据
    #一个整型数据占两个字节
    #一个字符占一个字节



    db = pymysql.connect(
        host='127.0.0.1',
        port=3306,
        user='root',
        password='123456',
        db='python_windu',
        charset='utf8') # 打开数据库,配置数据库
    cursor = db.cursor() # 数据库操作获取游标图像
    cursor.execute("DROP TABLE IF EXISTS Monitor_Data") # 如果存在表则重新创建
    creatTab = """CREATE TABLE Monitor_Data( # 创建表
    wendu FLOAT ,
    shidu FLOAT 
    
     )"""
     
    cursor.execute(creatTab) # 执行数据库语句

    def Recive_data(self,way):
        # 循环接收数据,此为死循环,可用线程实现
        print("开始接收数据:")
        t = 1;

        while True:
            try:
                # 一个字节一个字节的接收
                
                if self.main_engine.in_waiting:
                    if(way == 1):
                        for i in range(self.main_engine.in_waiting):
                            print("接收ascii数据:"+str(self.Read_Size(1)))
                            data1 = self.Read_Size(1).hex()#转为十六进制
                            data2 = int(data1,16)
                            #转为十进制
                            if( t%2 == 0 ):
                                print("收到数据十六进制:"+data1+"  温度:"+str(data2))
                            if( t%2 != 0 ):
                                print("收到数据十六进制:"+data1+"  湿度:"+str(data2))
                    if(way == 0):
                        
                        #整体接收
                        #data = self.main_engine.read(self.main_engine.in_waiting).decode("utf-8")
                        #方式一
                        
                        #方式二
                        db = pymysql.connect(
                             host='127.0.0.1',
                             port=3306,
                             user='root',
                             password='123456',
                             db='python_windu',
                             charset='utf8') # 打开数据库,配置数据库
                        if( t%2 != 0 ):
                            data1 = self.main_engine.read_all()
                            print("温度:", data1)
                            wendu =data1
                            
                        if( t%2 == 0 ):
                            data2 = self.main_engine.read_all()
                            print("湿度:", data2)
                            shidu=data2
                            sql = """INSERT INTO Monitor_Data(wendu, shidu)VALUES('%s', '%s')""" 
                            values = (float(wendu), float(shidu))
                            cursor = db.cursor()
                            cursor.execute(sql,values)
                            cursor.connection.commit()
                        
                        t = t+1;
            except Exception as e:
                print("异常报错:",e)
    

Communication.Print_Used_Com()
Ret =False #是否创建成功标志

Engine1 = Communication("com7",115200,0.5)
if (Ret):
    Engine1.Recive_data(0)

串口号、波特率等自行修改,且由于我的Navicat过期了,数据库的创建与连接就不举例了自行百度并修改上面相关的数据库连接数据。
代码中有一部分是写来实验正确性的,可自行删去或修改。

三、效果

  • 由于我的Navicat过期了,无法查看,用以前录好的图片于录像。

在这里插入图片描述

由于这个温湿度传感器是网上买的便宜的,之前用了一段时间湿度模块坏了,温度正常。

在这里插入图片描述
在这里插入图片描述

这是web部分可以从数据库读出数据来看,之前录的。

四、参考资料

通过读取串口数据,把数据写入MySQL.
python实现读取串口数据,并写入数据库.
Python连接MySQL数据库方法介绍.
Python+mysql数据库+传感器(将传感器获得数据存入数据库).

太多了…有些还找不到了。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_48008050/article/details/113267901