回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页
best-icon

【Mind+Python】基于BMP280气压传感器的玻意耳定律演示器 简单

头像 glwz007 2021.09.13 2668 8

一、关于玻意耳定律

玻意耳定律是高中物理中气体的等温变化规律,由英国物理学家玻意耳和法国科学家马略特各自通过实验发现。

玻意耳定律内容:一定质量的某种气体,在温度不变的情况下,压强P与体积V成反比,即:

project-image

上面本来是一个公式,但是word中的公式粘贴过来后无法识别,只好把公式存为图片,但是上传图片时又提示图片过小无法上传,无奈将图片尺寸放大才得以上传,但是看到的就是这个大大的公式了。

写成公式就是:

PV=C

式中C是常量。或者

P1V1=P2V2

式中P1、V1 和P2、V2 分别表示气体在1、2两个状态下的压强和体积。

二、传统的实验装置

在物理课的教学中,常用下面两种装置来验证玻意耳定律:

 1.利用注射器封闭一定质量的气体,通过气压计测量气体压强或者是在注射器活塞上加减砝码,间接测量气体压强,如下图1、2所示:

project-image

图1

project-image

图2

图1和图2相同之处都是利用注射器的活塞对筒内空气施加压力来改变气体的压强,这种实验方案操作简单,但是因为活塞跟筒壁之间的摩擦较大,图2中气压计分度值较大。两种装置中典型的问题是误差比较大,不利于实验结论的形成,而且实验装置可观察性不好,尤其是老师在课堂演示时,后排的同学基本上看不清楚实验装置和数据。

2.下图3是传统的实验装置,中间的液体用水银,在右管上升与下降过程中,左管中气体的体积发生明显的变化而压强的测量精度相对较高。但是水银的毒性比较大,不适合学生实验。

project-image

图3

三、基于气压传感器的创新实验装置

基于传统实验装置的不足之处,本装置利用注射器针筒封闭一定质量的气体,通过推拉活塞改变气体体积和压强,利用BMP280气压温度传感器测量筒内气体压强和温度,利用掌控板OLED屏幕实时显示测量的温度和气压,通过UDP以无线方式发送到电脑端,在电脑端以动态图表的形式实时显示测量结果,供班级内演示使用。

本装置利用BMP280气压温度传感器直接测量针筒内气体温度和压强,

避免了传统实验装置中摩擦阻力的影响,而且传感器测量及时,分度值小,误差很小。通过UDP无线方式发送测量数据到电脑端,在实际使用中能很好地验证气体的玻意耳定律,取得了良好的效果。

(一)主要硬件及介绍

1.掌控板

掌控板由创客教育专家委员会推出,是一款教学用开源硬件,为普及创客教育而生。如下图4所示,在巴掌大的板子上集成了ESP32主控芯片及各种传感器和执行器同时使用金手指的方式引出了所有IO口,性能强劲扩展性强,是创客、编程爱好者的创作工具。在本装置中作为主控板,并且利用掌控板的OLED屏幕显示测量数据。

project-image

图4

2.百灵鸽扩展板

百灵鸽扩展板是由N+实验室为掌控板研发的一款扩展板,如图5所示,该扩展板小巧轻便,外型美观,自带电源,还将掌控板的多数引脚引出,方便学习者外接其他传感器,实现自己的新奇想法。另外,加入了效果较好的扬声器、音频输出孔、SHT20温湿度传感器等,使掌控板能实现更多功能。

project-image

图5

3.BMP280气压温度传感器

如下图6所示,BMP280气压传感器基于博世经过验证的压阻式压力传感器技术,具有高精度和线性度以及长期稳定性和高EMC稳健性。气压传感器通常用于大气压检测和温度检测。气压检测范围:300—1100hPa,相对精度:±0.12hPa。温度测量范围:0℃—65℃,温度测量精度:0.01℃。

project-image

图6

4.医用50ml注射器(螺纹口)及对接转换接头。

本装置使用带有螺纹注射口的注射器及对接转换头,方便密封一定质量的气体,连接方便,气密性好。

project-image

图7

(二)编程软件

1.Mind+

Mind+,全名Mindplus,诞生于2013年,由DFRobot旗下子品牌蘑菇云创客教育发布,是一款拥有自主知识产权的国产青少年编程软件,集成各种主流主控板及上百种开源硬件,支持人工智能(AI)与物联网(IoT)功能,既可以拖动图形化积木编程,可以使用Python/C/C++等高级编程语言。适用于校内的编程教学、项目创作、创客比赛等场景,同时能满足学生校外进行创意编程与项目创造的需求。

project-image

图8

(三)制作过程

1.准备硬件:本装置用到的硬件清单如下:

材料清单

  • 掌控板 X1 链接
  • 百灵鸽掌控板扩展板 X1
  • BMP280气压温度传感器 X1
  • 医用50ml注射器(螺纹口) X2
  • 注射器对接转换接头(螺纹口) X1
  • 约50cm长四芯导线 X1
  • 密封胶 X1

2.硬件制作过程

(1)取出一个注射器活塞,在活塞中间开一小孔,将四芯导线穿过小孔。

(2)四芯导线的一段跟BMP280气压温度传感器触点焊接,另一端接杜邦线母头。这里采用导线直接跟线路板焊接的方式,没有焊接排针通过插头连接,是因为注射器内部空间有限,无法容纳排针跟插头。

(3)如下图9所示,将活塞连同BMP280气压温度传感器插入到注射器针筒内30ml处,用密封胶固定穿线孔及活塞。

project-image

图9

(4)如下图10所示,将四芯导线接杜邦线母头那端按照顺序接入百灵鸽扩展板IIC接口端。

project-image

图10

3.软件编程

软件编程方面分为掌控板端程序和电脑端程序两部分。

(1)掌控板端程序

①在电脑端安装Mind+软件,打开Mind+软件后选择“上传模式”,连接掌控板设备,扩展功能中添加主控“掌控板”、传感器模块“BME280模块”、网络服务“WI-FI”和“UDP广播”。

②通过拖动积木块的方式编写主程序,程序见附件。需要注意的是,WIFI连接语句中的WIFI名称和密码要与后面电脑端开启的WIFI热点信息一致。代码如下图11所示。

project-image

图11

③将右侧“自动生成”的代码粘贴到“手动编辑”栏,按下图12所示手动修改三处代码,然后将程序上传到掌控板。

project-image

图12

(二)电脑端程序

①在电脑端打开Mind+软件后选择“Python模式”,打开“库管理”,添加“matplotlib”库。

②在socket模块中绑定电脑端开启热点的IP地址,发送数据的端口号跟掌控板端接收数据的端口号一致。接受UDP方式从掌控板发送的传感器数据,利用matplotlib的animation功能绘制动图,建立双Y轴分别用两条图线显示BMP280传感器测量的气压值和温度值,具体程序代码如下。

(四)使用方法

1.在电脑端开启WIFI热点,WIFI名称和IP地址跟掌控板端程序中WIFI初始化设置一致。

2.开启掌控板电源,待掌控板连接网络后,会在屏幕显“网络连接成功”,三秒后如下图13所示,显示测量的温度和气压值,并通过UDP方式发送测量得到的传感器数值。

project-image

图13

3.运行电脑端程序,如下图14所示,即可显示传感器实时测量的气压值和温度值。

project-image

图14

4.如下图15所示,用对接转换接头将封闭有传感器的注射器与另一支注射器对接,将没有传感器的那支注射器活塞推到20ml处,然后缓慢的推拉活塞,即可改变气体的体积,通过针筒刻度读出气体体积,通过掌控板屏幕和电脑端图表,即可读出针筒内气体的温度和压强,根据记录的数据验证气体实验定律。

project-image

图15

5.某次实验中测测量数据如下图16所示,一定质量的气体,在温度一定是,压强与体积成反比,即压强与体积的乘积是一定值,实验数据测相对误差在1%左右,取得了良好的实验效果。

project-image

图16

四、后记

本项目基于掌控板+传感器+UDP网络技术制作,在制作过程中一边学习掌控板、传感器等硬件的相关知识,一边学习Mind+软件编程知识,在制作过程中得到了多位大咖老师的指点,并参考了论坛Ski老师的帖子:https://mc.dfrobot.com.cn/thread-308817-1-1.html,在此一并致谢!

掌控板端代码如下:

代码
/*!
 * MindPlus
 *
 */
#include <MPython.h>
#include <DFRobot_BMP280.h>
#include <DFRobot_UDPServer.h>

// 动态变量
String         mind_s_data;
volatile float mind_n_Temp, mind_n_Pres;
// 函数声明
String numberRetain(float t, uint8_t n);
// 创建对象
DFRobot_BMP280 bme280;
DFRobot_Iot        myIot;
DFRobot_UDPServer  myserver;


// 主程序开始
void setup() {
	mPython.begin();
	bme280.begin(0x76);
	mind_n_Temp = 0;
	mind_n_Pres = 0;
	display.fillScreen(0);
	display.setCursorLine(1);
	display.printLine("网络连接中...");
	myIot.wifiConnect("testwifi", "12345678");
	while (!myIot.wifiStatus()) {yield();}
	display.fillInLine(1, 0);
	display.setCursorLine(1);
	display.printLine("网络建立成功");
	delay(3000);
	display.fillInLine(1, 0);
	display.setCursorLine(1);
	display.printLine("        温度气压测量");
	myserver.setPort(8888);
}
void loop() {
	mind_n_Pres = (String((bme280.getPressure() / 100)).toInt());
	mind_n_Temp = (String((round((bme280.getTemperature() + 273.15)))).toInt());
	mind_s_data = (String(mind_n_Pres) + String((String(":") + String(mind_n_Temp))));
	myserver.sendUdpMsg(mind_s_data);
	display.setCursorLine(2);
	display.printLine((String("    温度:") + String((String(numberRetain(mind_n_Temp,0)) + String("K")))));
	display.setCursorLine(3);
	display.printLine((String("    压强:") + String((String(numberRetain(mind_n_Pres,0)) + String("hPa")))));
	display.setCursorLine(4);
	display.printLine("数据发送中...");
	delay(1000);
}


// 静态函数
String numberRetain(float t, uint8_t n)
{
  String str=t<0 ? "-" : ""; int8_t _n=n; t=abs(t);
  for(; _n>=0; --_n){
    uint32_t integer = floor(t);
    float decimal = t - integer;
    str += _n == n ? (String(integer) + (n ? "." : "")) : integer;
    t = decimal*10;
  }
  return str;
}

电脑端Python代码如下:

代码
# 造物记上传版

from matplotlib import pyplot as plt
import matplotlib.animation as animation
import datetime as dt
import matplotlib
import time
import socket

# 创建套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 绑定一个本地信息
localaddr = ("192.168.137.1",8888) # 必须绑定自己电脑IP和port
udp_socket.bind(localaddr)
data = []
matplotlib.rcParams['font.family'] = 'FangSong'  
fig = plt.figure(num = '气体温度压强测量', figsize=(12, 6), dpi = 100) 
ax1 = fig.add_subplot(1, 1, 1) 
ax1.yaxis.set_tick_params(labelcolor='b')
ax1.yaxis.set_tick_params(color='b')
ax2 = ax1.twinx() 
ax2.yaxis.set_tick_params(labelcolor='r') 
ax2.yaxis.set_tick_params(color='r')  
xs = []  
ys1 = [] 
ys2 = []  

def animate(i, xs, ys1,ys2):
    recv_data = udp_socket.recvfrom(1024)
    recv_msg = recv_data[0]
    send_addr = recv_data[1]
    data = recv_msg.decode("gbk").split(":")
    press = int(eval(data[0]))
    temp = int(eval(data[1]))
    xs.append(dt.datetime.now().strftime('%H:%M:%S'))
    ys1.append(press)
    ys2.append(temp)
    xs = xs[-20:]
    ys1 = ys1[-20:]
    ys2 = ys2[-20:]
    ax1.clear()
    ax2.clear()
    ax1.set_ylabel('气压P/×100Pa', color = 'b', size = 15)
    ax1.set_ylim(300,1600)
    ax1.tick_params('x', labelrotation=45)
    ax2.set_ylabel('热力学温度T/K', color = 'r', size = 15)
    ax2.set_ylim(270,380)
    ax1.plot(xs, ys1, 'b.-')
    ax2.plot(xs, ys2, 'r.:')
    plt.title('测量气体压强、温度', size = 20)
    for a, b, c in zip(xs, ys1, ys2):
        ax1.text(a, b, b, ha='center', va='bottom', color = 'b', fontsize=15, alpha = 0.5)
        ax2.text(a, c, c, ha='center', va='bottom', color = 'r', fontsize=15, alpha = 0.5)

ani = animation.FuncAnimation(fig, animate, fargs=(xs, ys1,ys2), interval=1000)
plt.show()
udp_socket.close()

演示视频:

第一次在makeblog发表文章,有不到之处,请多多指教,谢谢!

评论

user-avatar
  • Langston

    Langston2022.08.30

    老师您好 请问怎么知道掌控板端接受数据的端口号?感谢感谢

    0
    • 大哥哥

      大哥哥2022.08.10

      学习了

      0
      • digi_cow

        digi_cow2022.03.11

        学习了

        0
        • DFKK-SUN

          DFKK-SUN2021.12.19

          学习了

          0
          • 二哈666

            二哈6662021.10.05

            l

            0
            • 二哈666

              二哈6662021.10.05

              l

              0
              • glwz007

                glwz0072021.09.25

                非常抱歉,掌控板端代码遗漏一句: #include &lt;DFRobot_Iot.h&gt;

                0
                • glwz007

                  glwz0072021.09.13

                  请各位大咖多多指教,谢谢!

                  0