简 介: 本文给出了 MicroPython内核开发笔记:书内嵌入实验任务 中的utime软件用例部分内容。
关键词
: 软件,MicroPython,MM32F3277,utime,time
- 本书稿内容隶属于 MicroPython内核开发笔记:书内嵌入实验任务 中的内容。
软件用例:
这部分书稿内容包括有:
- 基础实验:交互查看 time 模块的基本功能;驱动LED 闪烁;
- 利用 time 测量软件执行时间,从而测量 端口信号的时间间隔。
- 书稿内位置:
§01 书稿内容
一、基础实验
1、查看time功能
通过以下命令,可以查看 time 的基本功能。
import time
dir(time)
time.ticks_cpu()
time.ticks_ms()
time.ticks_us()
命令输出结果为:
['__name__', 'sleep', 'sleep_ms', 'sleep_us', 'ticks_add', 'ticks_cpu', 'ticks_diff', 'ticks_ms', 'ticks_us']
158519
158520
158521000
>>>
从上面可以看到 time 中的主要功能包括有:
- 延迟命令: sleep, sleep_ms, sleep_us
- 时钟命令:ticks_cpu, ticks_ms, ticks_us, tikcs_diff
ticks_cpu 与 ticks_ms 实际上输出数值是一样的, ticks_us 是在 ticks_ms 的基础上仅仅乘以 1000,也就是这实际上是一个假的 us 时间延迟,对于一些需要高精度时间延时测量会产生不利影响。
2、闪烁LED
利用 time 的延迟功能,可以对主程序的循环做更加精确的控制。这在一些定时精度需要高的场合非常重要,比如使用主程序进行 PID 控制,要求控制循环周期严格保持设定的时长。所以精确延迟对于嵌入式软件开发非常中号。
下面程序利用 time 的延迟实现外部 LED 闪烁。
from machine import Pin
import time
led = Pin("PC0", mode=Pin.OUT_PUSHPULL)
while True:
led(1)
time.sleep_ms(250)
led(0)
time.sleep_ms(250)
下图显示了 LED 闪烁的情况。
▲ 图1.1.1 time延时产生LED闪烁
二、延时的精度
对上面 LED 闪烁实验中,通过测量设置不同的 time.sleep_ms 数值对应 LED 闪烁频率,分析 time 延时时间精度。
下面是对 time 延时 n 分别取值从 1 到 25变化,输出 LED 方波频率数值。
▲ 对应不同time延时测量LED闪烁频率
n取值 | 输出频率值(Hz) |
---|---|
1 | 200.009995 |
2 | 133.339996 |
3 | 100.0 |
4 | 80.0 |
5 | 66.669998 |
6 | 57.150002 |
7 | 50.0 |
8 | 44.450001 |
9 | 40.0 |
10 | 36.369999 |
11 | 33.330002 |
12 | 30.77 |
13 | 28.57 |
14 | 26.67 |
15 | 25.0 |
16 | 23.530001 |
17 | 22.219999 |
18 | 21.049999 |
19 | 20.0 |
20 | 19.049999 |
21 | 18.18 |
22 | 17.389999 |
23 | 16.67 |
24 | 16.0 |
25 | 15.39 |
通过对上述数值区间利用函数 1 / f = 2 a ⋅ ( n + b ) 1/f = 2a \cdot \left( {n + b} \right) 1/f=2a⋅(n+b) 进行拟合,可以求得 a,b 大约为 1.25 和 1。因此,通过这个时间可以证明,在这个版本所实现的 time 延时中,存在着系统误差。 对于 time.sleep_ms(n) 语句,实际上延时时间为 1.25(n+1) ms。
三、测量实验
应用 time 中的 ticks_cpu 可以获得程序两段代码之间的时间延时,这个特性可以 应用在超声测量、电容充放电时间等,也可以用于测量 MicroPython 程序执行所消耗的时间,这在进行程序优化方面具有重要的意义。
很可惜,现在的这个版本只能够提供 ms 级别的时间分辨率。因此如果提高测量精度,还需要改进内部实现机制。
下面这个应用了单片机管脚可以配置成输入输出的模式,并对外部输入电压具有比较特性。应用 RC 充放电特性可以测量未知电容容量。测量电路如下所示,其中 R1 是已知电阻,实验中采用 10kΩ。 C1是待测电容。
▲ 图1.3.1 测量电容实验电路
测量前,将 PC1 配置成输出模式,将 C1 上的电压释放到 0V 左右。 然后将 PC1 设置成高阻输入状态, 3.3V 电源将通过 R1 对 C1 进行充电,当输入电压超过端口阈值电压 U 1 U_1 U1 之后, PC1 输入逻辑从 0 变成 1,利用 time 的 ticks_cpu 函数获得这个充电时间 t 1 t_1 t1 。 根据 RC 充放电规律可知 t 1 = R 1 C 1 ⋅ ln ( 3.3 3.3 − U 1 ) t_1 = R_1 C_1 \cdot \ln \left( { { {3.3} \over {3.3 - U_1 }}} \right) t1=R1C1⋅ln(3.3−U13.3)
再根据已知 R1 的数值,便可以计算出待测 C1 的容值了。
下面是测试程序。
from machine import Pin
import time
pinc = Pin("PC1", Pin.OUT_OPENDRAIN)
pinc(0)
def measureC():
startc = time.ticks_cpu()
pinc = Pin("PC1", Pin.IN_FLOATING)
time.sleep_ms(1)
while True:
if pinc.value() != 0:
endc = time.ticks_cpu()
break
pinc = Pin("PC1", Pin.OUT_OPENDRAIN)
pinc(0)
return endc - startc
while True:
ret = measureC()
print(ret)
time.sleep_ms(1000)
如下是待测电容上的电压波形。 可以查看到,电压充到 1.84V,对应阈值电压 U 1 = 1.84 V U_1 = 1.84V U1=1.84V 。
▲ 待测C1上的电压波形
程序运行返回的数值为 65。 根据前面延时精度测量可知,实际充电时间 t 1 = 65 × 1.25 = 81.25 m s t_1 = 65 \times 1.25 = 81.25\,ms t1=65×1.25=81.25ms 。根据已知 R 1 = 10 k Ω R_1 = 10k\Omega R1=10kΩ ,可以得到待测电容
C 1 = 81.25 R 1 ln 3.3 3.3 − U 1 = 9.97 μ F C_1 = { {81.25} \over {R_1 \ln { {3.3} \over {3.3 - U_1 }}}} = 9.97\mu F C1=R1ln3.3−U13.381.25=9.97μF
这个数值与电容的标称值 10微法 很接近。
※ 总 结 ※
本文给出了 MicroPython内核开发笔记:书内嵌入实验任务 中的utime软件用例部分内容。
一、修改建议
1、延时系统误差
通过实验可以看到,在移植软件版本中,time 延时时间存在着系统误差,也就是移植软件存在着BUG,这是编程人员通常会犯的错误。按照现在的版本, time.sleep_ms(n) 实际延时为 1.25(n+1) ms。 建议将这部分 BUG 修改掉。
2、实现真正 us 延时
在 time.ticks_us(), ticks_cpu() 最好能够实现内部高精度定时器。
■ 相关文献链接:
● 相关图表链接: