自由落体运动加速度的测量是中学物理的一个实验。较早的方法是通过打点计时器来测量重物下落的距离以及时间,从而计算出自由落体运动的加速度。但该方法用到了专业的打点计时器,且可能受到摩擦力导致测量误差。因此,本实验用行空板、激光测距传感器、红外对射模块,舵机等作为主控来测量自由落体时长,进一步得到加速度。
实验目的
- 学会用自由落体法测定重力加速度;
- 了解并掌握pinpong控制舵机、激光测距传感器的使用方法;
- 学会使用行空板做数据的处理与显示;
实验原理
自由落体运动是初速度为零的匀变速直线运动,其运动方程为:
h = 1 /2 gt²
其中,h表示t时间内物体下落的高度,只需测出h和t,就可求得重力加速度g,即:
g = 2h /t²
实验器材
序列 |
硬件名称 |
硬件数量 |
1 |
行空板 |
1 |
2 |
VL53L0X ToF 激光测距传感器 |
1 |
3 |
红外对射传感器 |
1 |
4 |
9克舵机 |
1 |
功能设计
电路连接
-
舵机---------------D23
-
红外对射传感器------------D24
-
激光测距传感器 ----------IIC通讯
外型设计
使用fusion360设计出该装置的外形
实验步骤
实验一、绘制UI界面
说明:因为我们的UI界面是由一系列图片组成的,主要用到了unihiker库中的基础空间中的draw_image()函数实现。所以我要先将准备好的素材导入【文件目录】---【项目中的文件】中,具体操作如下图所示:
然后点击右侧项目中的文件后面的新建文件按钮,创建一个mian.py创建好后,双击它,开始进行代码的编写
Code:
from unihiker import GUI
import time
gui=GUI()
def home():# 主页
gui.clear()
gui.draw_image(image="bg.png",x=0,y=0)
gui.draw_image(image="start.png",x=135,y=120,onclick=bt1_click) # 开始
gui.draw_image(image="display.png",x=80,y=120,onclick=bt2_click) # 生成数据
gui.draw_image(image="clear.png",x=20,y=120,onclick=bt3_click) # 清除数据
def bt1_click():
print("bt1 click")
def bt2_click():
print("bt2 click")
def bt3_click(): # 清空数据
print("bt3 click")
home()
while True:
time.sleep(0.1)
实验效果:
点击UI界面的按钮图片,终端也会显示其响应函数打印出的信息。
实验二:计算并显示重力加速度值
这里我们需要用到pinpong库实现对舵机、VL53L0X ToF 激光测距传感器、红外对射模块的调用。
首先先对各个模块进行测试,确保它们是正常运行的。
舵机测试:
# -*- coding: utf-8 -*-
#实验效果:舵机控制
#接线:使用windows或linux电脑连接一块行空板,D23连接一个舵机
import time
from pinpong.board import Board,Pin,Servo
Board().begin() #初始化,选择板型和端口号,不输入端口号则进行自动识别
s1 = Servo(Pin(Pin.D23)) #将Pin传入Servo中初始化舵机引脚
while True:
s1.angle(0) #控制舵机转到0度位置
print("S1 0")
time.sleep(1)
s1.angle(180) #控制舵机转到180度位置
print("S1 180")
time.sleep(1)
红外对射模块测试:
# -*- coding: utf-8 -*-
#实验效果:终端打印引脚状态
#接线:使用windows或linux电脑连接一块行空板,主控板D24接一个红外对射模块
import time
from pinpong.board import Board,Pin
Board().begin() #初始化,选择板型和端口号,不输入端口号则进行自动识别
ir_state = Pin(Pin.D24, Pin.IN) #引脚初始化为电平输入
while True:
state = ir_state.read_digital() #读取数字引脚值 True 0r False
print(state) #终端打印读取的电平状态
time.sleep(0.1)
VL53L0X ToF 激光测距传感器测试
注:Q:这里为什么要用这款激光测距模块而不用超声波模块呢?
A:因为超声波的体积太大使装置整体不够美观,与行空板接线比较复杂及精度不够高容易对实验造成误差!所以选用了这款VL53L0X ToF 激光测距传感器,它体积小,使用IIC通讯VL53L0X无论目标反射率如何,都能提供精确的距离测量。
# -*- coding: utf-8 -*-
import time
from pinpong.board import Board
from pinpong.libs.dfrobot_vl53l0 import VL53L0
Board().begin()#初始化,选择板型和端口号,不输入端口号则进行自动识别
vl = VL53L0()
while True:
distance = vl.get_distance_mm()
print("distance: %.2f mm"%(distance))
time.sleep(0.5)
code:
from pinpong.libs.dfrobot_vl53l0 import VL53L0
from pinpong.board import Board,Pin,Servo
from pinpong.board import Servo
from unihiker import GUI
import time
gui=GUI()
Board().begin()
bt_state=Pin(Pin.P24, Pin.IN)
s1 = Servo(Pin(Pin.P23)) #将Pin传入Servo中初始化舵机引脚
s1.angle(180) # 舵机初始化
vl = VL53L0()
dist_list = []
time_list = []
data_list = []
err_lsit = []
g_local = 9.7947 #合肥本地重力加速度
def home():# 主页
gui.clear()
gui.draw_image(image="bg.png",x=0,y=0)
gui.draw_image(image="start.png",x=135,y=120,onclick=bt1_click) # 开始
gui.draw_image(image="display.png",x=80,y=120,onclick=bt2_click) # 生成数据
gui.draw_image(image="clear.png",x=20,y=120,onclick=bt3_click) # 清除数据
def bt1_click(): #开始测试
distance = (vl.get_distance_mm() )/1000 # 获取当前高度
s1.angle(120) # 打开舵机
temp_time = time.time() # 记录物体自由落体下落前的时间
while not (bt_state.read_digital()==False):
pass
temp_time = time.time() - temp_time -0.06
g_value = (2*distance) / (temp_time **2) # 计算重力加速度
err_value = g_local - g_value # 计算误差
temp_time = round(temp_time,4) # 取小数点后四位
g_value = round(g_value,4)
err_value =round(err_value,4)
if err_value < 0.5:
dist_list.append(distance) #将测量高度distance添加到dist_list列表中
time_list.append(temp_time) #将测量时间temp_time添加到time_list列表中
data_list.append(g_value) #将测量重力加速度值g_value添加到data_list列表中
err_list.append(err_value) #将测量误差err_value添加到err_lsit列表中
# 数据显示
gui.clear()
gui.draw_text(text="高度:" +str(distance) ,x=220,y=50,font_size=15,color="#000000",angle=270)
gui.draw_text(text="时间:" +str(temp_time) ,x=180,y=50,font_size=15,color="#000000",angle=270)
gui.draw_text(text="重力加速度:" +str(g_value) ,x=140,y=50,font_size=15,color="#000000",angle=270)
gui.draw_text(text="误差:" +str(err_value) ,x=100,y=50,font_size=15,color="#000000",angle=270)
gui.draw_image(x=30, y=240, image='back.png', origin='center',onclick=home)
else :
gui.clear()
gui.draw_text(text="误差有误请重新测量",x=150,y=40,font_size=20,color="red",angle=270)
gui.draw_image(x=30, y=240, image='back.png', origin='center',onclick=home)
s1.angle(180)
def bt2_click():
print("bt2 click")
def bt3_click(): # 清空数据
print("bt3 click")
home()
while True:
time.sleep(0.1)
实验效果:
数据在正常误差范围内显示,如下图所示:
数据有误时提示:
实验三:生成多个实验数据
先通过unihiker内置的库函数,来做一个显示数据的界面,具体函数如下
def data_display(): # 数据显示
gui.clear()
gui.draw_line(x0=200, y0=0, x1= 200, y1=320, width=2, color=(0,0,0))
gui.draw_text(text="自由落体实验结果",x=230,y=80,font_size=15,color="#000000",angle=270) #表头
gui.draw_text(text="自由落体高度",x=190,y=30,font_size=8,color="#000000",angle=270)
gui.draw_text(text="时长",x=190,y=110,font_size=8,color="#000000",angle=270)
gui.draw_text(text="重力加速度",x=200,y=150,font_size=8,color="#000000",angle=270)
gui.draw_text(text="测量",x=190,y=250,font_size=8,color="#000000",angle=270)
gui.draw_text(text="(m)",x=175,y=50,font_size=8,color="#000000",angle=270)
gui.draw_text(text="(ms)",x=175,y=110,font_size=8,color="#000000",angle=270)
gui.draw_text(text="测量值(m/s²)",x=175,y=155,font_size=8,color="#000000",angle=270)
gui.draw_text(text="误差",x=175,y=250,font_size=8,color="#000000",angle=270)
gui.draw_line(x0=150, y0=0, x1= 150, y1=320, width=1, color=(0,0,0))
gui.draw_line(x0=50, y0=0, x1= 50, y1=320, width=2, color=(0,0,0))
gui.draw_image(x=30, y=240, image='back.png', origin='center',onclick=home)
显示效果:
前面我们用列表存储了实验数据(距离,时间,重力加速度值,误差),现在需用通过列表遍历的方式将它显示在行空板的屏幕上,具体代码如下:
code:
from pinpong.libs.dfrobot_vl53l0 import VL53L0
from pinpong.board import Board,Pin,Servo
from pinpong.board import Servo
from unihiker import GUI
import time
gui=GUI()
Board().begin()
bt_state=Pin(Pin.P24, Pin.IN)
s1 = Servo(Pin(Pin.P23)) #将Pin传入Servo中初始化舵机引脚
s1.angle(172) # 舵机初始化
vl = VL53L0()
dist_list = []
time_list = []
data_list = []
err_lsit = []
g_local = 9.7947 #合肥本地重力加速度
def home():# 主页
gui.clear()
gui.draw_image(image="bg.png",x=0,y=0)
gui.draw_image(image="start.png",x=135,y=120,onclick=bt1_click) # 开始
gui.draw_image(image="display.png",x=80,y=120,onclick=bt2_click) # 生成数据
gui.draw_image(image="clear.png",x=20,y=120,onclick=bt3_click) # 清除数据
def data_display(): # 数据显示
gui.clear()
gui.draw_line(x0=200, y0=0, x1= 200, y1=320, width=2, color=(0,0,0))
gui.draw_text(text="自由落体实验结果",x=230,y=80,font_size=15,color="#000000",angle=270) #表头
gui.draw_text(text="自由落体高度",x=190,y=30,font_size=8,color="#000000",angle=270)
gui.draw_text(text="时长",x=190,y=110,font_size=8,color="#000000",angle=270)
gui.draw_text(text="重力加速度",x=200,y=150,font_size=8,color="#000000",angle=270)
gui.draw_text(text="测量",x=190,y=250,font_size=8,color="#000000",angle=270)
gui.draw_text(text="(m)",x=175,y=50,font_size=8,color="#000000",angle=270)
gui.draw_text(text="(ms)",x=175,y=110,font_size=8,color="#000000",angle=270)
gui.draw_text(text="测量值(m/s²)",x=175,y=155,font_size=8,color="#000000",angle=270)
gui.draw_text(text="误差",x=175,y=250,font_size=8,color="#000000",angle=270)
gui.draw_line(x0=150, y0=0, x1= 150, y1=320, width=1, color=(0,0,0))
gui.draw_line(x0=50, y0=0, x1= 50, y1=320, width=2, color=(0,0,0))
gui.draw_image(x=30, y=240, image='back.png', origin='center',onclick=home)
# 通过遍历列表的方式将数据显示在
for i in range(len(data_list)):
gui.draw_text(text=str(dist_list[i]),x=140-20*i,y=40,font_size=8,color="#000000",angle=270)
gui.draw_text(text=str(time_list[i]),x=140-20*i,y=110,font_size=8,color="#000000",angle=270)
gui.draw_text(text=str(data_list[i]),x=140-20*i,y=180,font_size=8,color="#000000",angle=270)
gui.draw_text(text=str(err_lsit[i]),x=140-20*i,y=250,font_size=8,color="#000000",angle=270)
def bt1_click():
print("bt1 click")
distance = (vl.get_distance_mm() )/1000 # 获取当前高度
s1.angle(110) # 打开舵机
temp_time = time.time() # 记录物体自由落体下落前的时间
while not (bt_state.read_digital()==False):
pass
temp_time = time.time() - temp_time
g_value = (2*distance) / (temp_time **2) # 计算重力加速度
err_value = g_local - g_value # 计算误差
temp_time = round(temp_time,4) # 去小数点后四位
g_value = round(g_value,4) #
err_value =round(err_value,4) #
dist_list.append(distance) #将测量高度distance添加到dist_list列表中
time_list.append(temp_time) #将测量时间temp_time添加到time_list列表中
data_list.append(g_value) #将测量重力加速度值g_value添加到data_list列表中
# 数据显示
gui.clear()
gui.draw_text(text="高度:" +str(distance) ,x=220,y=50,font_size=15,color="#000000",angle=270)
gui.draw_text(text="时间:" +str(temp_time) ,x=180,y=50,font_size=15,color="#000000",angle=270)
gui.draw_text(text="重力加速度:" +str(g_value) ,x=140,y=50,font_size=15,color="#000000",angle=270)
gui.draw_text(text="误差:" +str(err_value) ,x=100,y=50,font_size=15,color="#000000",angle=270)
gui.draw_image(x=30, y=240, image='back.png', origin='center',onclick=home)
s1.angle(180)
def bt2_click():
data_display()
print("bt2 click")
def bt3_click(): # 清空数据
print("bt3 click")
dist_list.clear()
time_list.clear()
data_list.clear()
gui.clear()
gui.draw_text(text="数据已清空",x=150,y=100,font_size=20,color="#000000",angle=270)
gui.draw_image(x=30, y=240, image='back.png', origin='center',onclick=home)
home()
while True:
time.sleep(0.1)
实验效果:
总结:
通过本次实验:我们学会自由落体测量重力加速度的方法以及行空板的基础使用方法!我们在用自由落体测量加速度时,会发现有很多误差因素干扰实验结果,比如:激光测距传感器的精度,红外对射模块监测自由落体的时间,舵机控制的时间等都会对实验有所影响。所以有些地方需要我们做误差分析及补偿,让实验结果趋近于目标值。