1.1 背景介绍
在博文 线上比赛无线充电组仲裁申请以及检查结果[1] 记录了第十七届智能车竞赛[2]全国总决赛中山魂八队比赛受到参赛队伍质疑的问题。山魂八队为何受到质疑,主要一个原因来自于网络直播比赛过程中,远程观看山魂八队车模显示电压的 LED 灯柱出现三个一排的点亮以及出现突然变亮和变暗虚亮的情况。在 对于山东威海-无线充电组技术报告中的疑问及其回复[3] 给出了山魂八队的技术报告及其相关质疑和回复。特别是技术报告中给出了山魂八队无线充电组 LED 灯柱的硬件原理图以及循环点亮的程序算法。
那么,根据上面的技术资料,是否可以重现 LED 灯柱以及显示特性呢?本文就搭建相应的实验电路,测试一下视频中的奇特现象。
1.2 测试方案
由于只是测试山魂八队 LED 灯柱的显示特性,所以并不完全按照他们的硬件电路进行搭建,而是将其中的显示基本原理保持一致即可。下面分别给出测试硬件和软件设计方案。
1.2.1 灯柱显示根据 第十七届智能车竞赛技术报告-无线充电组-山东大学(威海)[4] 可以知道他们将灯柱中的 15 个 LED 分成5×3 的阵列,每一行由三个 LED 组成,通过一个 MOS 管驱动。使用一片 Infineon 公司的 LED 专用驱动芯片 TLD2331 来驱动三列。通过动态扫描的方式完成 15 个 LED 的点亮。
▲ 图1.2.1 山大威海无线组灯柱驱动电路示意图
为了简化测试的过程,这里只是在面包板上搭建了前两行 LED 显示灯柱。组成 2×3 的阵列。具体面包板上的电路如下图所示。
▲ 图1.2.2 在面包板上搭建的两列LED灯柱显示测试电路
1.2.2 ESP32平台
控制信号使用了MicroPython ESP32 平台,相关的技术资料参见 ESP32-S模块转接板设计与实现[5]。下面是将该接口板的原理图转帖过来。
▲ 图1.2.3 ESP32测试版接口图
(1)端口配置
使用其中GPIO32,33,35,26,27分别控制 LED 灯柱的行与列。实际上通过测试发现, ESP32 的所有 GPIO 中,并不是所有的 GPIO 都适合做输出端口,最终使用其中的 32,33,25,27,26 来驱动 LED 灯柱,在后面实验中又替换成其它端口。
(2)软件编程
根据 MicroPython ESP32[6] 编程文档,控制六个 LED 灯柱闪烁, 闪烁的频率大约是 50Hz。由于是软件控制,所以实测闪烁频率为 49.73Hz。
from machine import Pin
import time
led = Pin(5, Pin.OUT)
row1 = Pin(32, Pin.OUT)
row2 = Pin(33, Pin.OUT)
row3 = Pin(25, Pin.OUT)
col1 = Pin(26, Pin.OUT)
col2 = Pin(27, Pin.OUT)
print("Test LED .")
row1.on()
row2.on()
row3.on()
while True:
col1.on()
col2.on()
led.on()
time.sleep_ms(10)
col1.off()
col2.off()
led.off()
time.sleep_ms(10)
1.3 测试结果
1.3.1 摄像机观察结果
通过摄像机观察50Hz闪烁的灯柱, 可以看到LED灯柱亮度平稳,没有闪烁。这与人眼观察到的现象是相同的。
▲ 图1.3.1 通过摄像机观察到的LED灯柱亮度
1.3.2 通过手机观察结果
通过手机观察50Hz闪烁的 LED 灯柱亮度,可以看到 LED 灯柱在闪烁。
▲ 图1.3.2 通过手机观察LED亮度变化
1.3.3 使用硬件中断
由于前面利用了软件延迟,所以 LED 闪烁的频率不是准确的 50Hz,下面利用 ESP32 的硬件时钟中断,产生更加准确的 50Hz 闪烁。
(1)实验程序from machine import Pin,Timerimport time
led = Pin(5, Pin.OUT)
row1 = Pin(32, Pin.OUT)
row2 = Pin(33, Pin.OUT)
row3 = Pin(25, Pin.OUT)
col1 = Pin(26, Pin.OUT)
col2 = Pin(27, Pin.OUT)
print("Test LED .")
row1.on()
row2.on()
row3.on()
ledcount = 0
flag = 0
def ledflash(_):
global ledcount,flag
ledcount += 1
if ledcount >= 10:
if flag * 0:
flag = 1
col1.on()
col2.on()
else:
flag = 0
col1.off()
col2.off()
ledcount = 0
time0 = Timer(0)
time0.init(period=1, mode=Timer.PERIODIC, callback=ledflash)
while True:
led.on()
time.sleep_ms(10)
led.off()
time.sleep_ms(10)
(2)手机观察现象
下面是使用手机拍摄的 LED 灯柱亮度闪烁的情况。
▲ 图1.3.3 使用手机拍摄的LED亮度变化
(3)摄像头观察情况
下面是使用 HDMI 接口的摄像头拍摄到的 LED 灯柱亮度闪烁的情况。
1.3.4 分析结果
通过上面测试,可以看到 LED 灯柱如果高频闪烁的时候, 闪烁频率很高,由于视觉暂留现象,人眼看到是平均的稳定亮度,并不闪烁。但是在手机摄像头中,当闪烁频率接近摄像头图像帧频率时,可能观察到到亮度闪烁的情况。这解释了在比赛中远程观察到的山魂八队 LED 灯柱呈现闪烁的情况。
为了说明比赛中山魂八队无线充电组 LED 灯柱的如下奇特现象:
- 观察到其 LED 灯柱似乎是三个一组同时点亮和熄灭;
- 在运行中会出现 LED 灯虚亮 的情况;
下面根据 第十七届智能车竞赛技术报告-无线充电组-山东大学(威海)[2] 中给出的 LED 灯柱控制核心程序进行测试,看是否能够复现出上述现象,并进行解释。
2.1 LED控制软件2.1.1 山魂八队原始程序
下面是山魂八队的控制程序。从整体上分为两部分, 前面是设置行 MOS 管导通状态,后面部分设置 TLD2331 的三列输出。根据程序可以知道,GPIO输出为 0 的时候, TLD2331输出高电平。
▲ 图2.1 山魂八队无线充电组LED灯柱控制程序
2.1.2 ESP32测试程序
在一开始,完全根据上述单片机 C 语言程序的逻辑,编写了对应的 MicroPython 程序进行测试,发现该程序运行后, LED 灯柱点亮时出现问题。
(1)MicroPython测试程序下面是测试 MicroPython 程序。
from machine import Pin,Timerimport time
print("Test LED .")
led = Pin(5, Pin.OUT)
row1 = Pin(32, Pin.OUT)
row2 = Pin(12, Pin.OUT)
row3 = Pin(13, Pin.OUT)
col1 = Pin(26, Pin.OUT)
col2 = Pin(27, Pin.OUT)
col3 = Pin(14, Pin.OUT)
col1.off()
col2.off()
col3.off()
row1.off()
row2.off()
row3.off()
ledcount = 0
flag = 0
voltage_light = 1
column_count = 0
def ledflash(_):
global ledcount,flag,voltage_light,column_count
column_count += 1
if column_count >= 4: column_count = 0
light_row = voltage_light//3
light_column = voltage_light%3
if column_count == 0:
if light_row >= 0: col1.on()
else: col1.off()
elif column_count == 1:
if light_row >= 1: col2.on()
else: col2.off()
elif column_count == 2:
if light_row >= 2: col3.on()
else: col3.off()
if column_count < light_row:
row1.on()
row2.on()
row3.on()
elif column_count > light_row:
row1.off()
row2.off()
row3.off()
else:
if light_column == 0:
row1.on()
row2.off()
row3.off()
elif light_column == 1:
row1.on()
row2.on()
row3.off()
elif light_column == 2:
row1.on()
row2.on()
row3.on()
else:
row1.off()
row2.off()
row3.off()
time0 = Timer(0)
time0.init(period=1, mode=Timer.PERIODIC, callback=ledflash)
while True:
led.on()
time.sleep_ms(250)
led.off()
time.sleep_ms(250)
voltage_light += 1
if voltage_light >= 6:
voltage_light = 0
(2)出现的问题
上述程序是每隔 0.5 秒,将表示电压的 voltage_light 变量增 1。当到达 6 时返回0。本希望能够看到 LED 灯柱逐步从 1 个 LED 点亮,逐步增加到 6 个 LED 都点亮。但实际运行结果是:
- 前三个 LED 可以顺序点亮;
- 但后面三个 LED 则同时点亮;
这个现象与山大威海无线充电组车模在比赛时表现的状况很相似,他们比赛的时候也是三个 LED 一组同时点亮。
▲ 图2.1.2 . 测试LED灯柱运行状况
2.1.3 问题解决
(1)错误分析
上面错误来源于山大威海编程中的错误。按照 LED 矩阵扫描原理,每一次只能够选择一个 MOS 管导通,但是按照前面论文中的程序,可以看到随着 voltage_light 增加, 导通的 MOS 管会逐步增多。这就会使得同时点亮的行之间相互干扰。具体表现上就是除了第一行之外,其它各行的三个 LED 都是同时被点亮。
比如:当变量 voltage_light 在 3 - 5V 之间时, MOS 管 T1,T2 都会导通,这样就会使得前面的 L1-L6 都会被同时点亮。
▲ 图2.1.3 原始程序存在的BUG
(2)修改代码
实际上,程序代码可以进行简化,根据 column_count 分别控制 col1,col2,col3 为高电平。如下面代码所示:
col1.off()col2.off()
col3.off()
if column_count * 0: col1.on()
elif column_count * 1: col2.on()
elif column_count * 3: col3.on()
(3)运行效果
将原来的程序进行简化之后,LED灯柱的显示就正常了。随着 voltage_light 变量的增加,灯柱逐步点亮。
▲ 图2.1.4 . 修改后LED灯柱显示效果
2.2 LED闪烁与虚亮
在前面给出了 LED 灯柱在摄像头中闪烁的情况,下面再对比 LED 灯柱在摄像机和摄像头下不同的闪烁情况。设置 ESP32 测试程序定时器中断的周期为 5ms,那么程序扫描周期为 20ms,与前面测试灯柱闪烁的频率一致。
(1)摄像机下的图像
在摄像机下, 可以看到 LED 灯柱亮度是恒定的,看不出任何闪烁的情况。
▲ 图2.2.1 . 摄像机下LED灯柱亮度情况
(2)手机下的图像
使用手机拍摄 LED 灯柱,可以看到它的亮度出现非常明显的闪烁现象。
以上对比可以看到在普通手机摄像头里,对于扫描频率较低的LED灯柱会出现比较明显的闪烁现象。因此,为了避免这种闪烁,最简单的办法就是提高LED矩阵扫描频率,也可以通过修改扫描频率,来避免这种明显的拍频的现象。
2.2.2 虚亮现象(1)什么是虚亮现象?
上述程序中,还存在着一个 “虚亮现象”,也就是 LED 灯在未点亮之前会被微弱的点亮。比如在点亮 LED1,LED2的时候,对应的 LED4,LED5 也会被 “微弱的点亮” 。 下图是截取了测试电路板在点亮 LED1、LED2 的时候,观察到 LED4、LED5 也被点亮的情况。
▲ 图2.2.3 LED灯柱出现虚亮现象
由于测试电路板上的 LED 是依靠 ESP32 的端口驱动,所以输出电流很小。如果是 TLD2331 驱动,这种虚亮 的 LED 会在瞬间变得非常亮, 根据前面闪烁现象可以知道,在手机摄像头所拍摄到的视频中,这些瞬间点亮的 LED 会被看成点亮的LED。这种虚亮现象也就能回答在 线上比赛无线充电组仲裁申请以及检查结果[7] 同学提示的疑问,也就是看到过 1、2、4、6、 8.... 这样不连续点亮的情况。
(2)怎么产生的虚亮?虚亮问题的产生也是由 山大威海 无线充电组 LED 灯柱程序引起的。原始程序是先对控制行输出的 IO 口进行设置,然后再对控制列的 IO 口进行设置。问题在于开始设置行 IO 口的时候,并没有关闭列IO 口,这样就会在切换行 IO 口时,前面打开的列 IO 口会点亮后面一行的 LED。这样就会在行列 IO 口改变中间的时候,使得后面一行的 LED 可能会被瞬间点亮。
(3)如何消除虚亮现象?实际上只要在每一个进入中断进行 LED 矩阵扫描的时候,先对列禁止输出,然后依次设置行 IO 和列 IO 状态,就可以避免“虚亮” 现象了。下面是修改后的 LED 中断扫描程序。
def ledflash(_):global ledcount,flag,voltage_light,column_count
column_count += 1
if column_count >= 4: column_count = 0
light_row = voltage_light//3
light_column = voltage_light%3
row1.off()
row2.off()
row3.off()
col1.off()
col2.off()
col3.off()
if column_count == 0: col1.on()
elif column_count == 1: col2.on()
elif column_count == 3: col3.on()
if column_count < light_row:
row1.on()
row2.on()
row3.on()
elif column_count > light_row:
row1.off()
row2.off()
row3.off()
else:
if light_column == 0:
row1.on()
row2.off()
row3.off()
elif light_column == 1:
row1.on()
row2.on()
row3.off()
elif light_column == 2:
row1.on()
row2.on()
row3.on()
else:
row1.off()
row2.off()
row3.off()
下面是摄像机拍摄到的程序修改后的 LED 灯柱点亮的情况,已经彻底消除了 “虚亮” 的现象了。
智能车竞赛山大威海无线充电队伍山魂八队在远程比赛过程中,视频显示他们的 LED 灯柱出现的奇怪现象,包括有:(1) 三个 LED 同时点亮;(2) 出现 LED 虚亮的现象。本文根据山魂八队提交的技术报告中的硬件和软件,使用自制 ESP32 电路板,利用 MicroPython 编程,测试了 LED 灯柱电路和控制软件。指出了他们技术报告中 LED灯柱控制软件存在的问题,并提出了修改办法。在一定程度上解释了远程比赛视频中出现的奇怪现象。
特别是虚亮现象,在现场人眼是不易觉察出,但通过摄像头捕捉之后就有可能显示出被超前点亮现象,这使得远程观看比赛视频中往往会出现显示的电压突变和虚高现象,从而引起围观者的各种的猜疑。
比赛虽然结束了,但我们仍然忘不了其中的纷纷扰扰,争争执执。也许其中还有很多秘密我们还不知道,但行胜于言,通实验验数据验证猜测,将会让我们懂得更多,走得更远,也许这正是智能车竞赛令人着迷的地方吧。
▲ 图3.1 飞行中的小鸟
人们总以为眼见为实,有图有真相。但实际过程中,眼睛看到的未必是实际情况。上面动图是在推文 数码内外,天壤之别[8] 显示了某人家监控拍摄到屋檐下小鸟飞行的情况。为何这个小鸟翅膀不动但能够灵活的左右飞行呢?
参考资料[1]
线上比赛无线充电组仲裁申请以及检查结果: https://blog.csdn.net/zhuoqingjoking97298/article/details/126536052?spm=1001.2014.3001.5501
[2]第十七届智能车竞赛: https://blog.csdn.net/zhuoqingjoking97298/article/details/110253008
[3]对于山东威海-无线充电组技术报告中的疑问及其回复: https://blog.csdn.net/zhuoqingjoking97298/article/details/126575012?spm=1001.2014.3001.5501
[4]第十七届智能车竞赛技术报告-无线充电组-山东大学(威海): https://zhuoqing.blog.csdn.net/article/details/126573548
[5]ESP32-S模块转接板设计与实现: https://zhuoqing.blog.csdn.net/article/details/115563474
[6]MicroPython ESP32: https://docs.micropython.org/en/latest/esp32/quickref.html
[7]数码内外,天壤之别: https://mp.weixin.qq.com/s?__biz=MzA5NjQyNjc2NQ&mid=2452246873&idx=1&sn=5328041eb1c9ee48ac5afb4ad8a82ba2&chksm=876ebf3bb019362d29b157ea9cf58841ac56cc144736f10d1dc567d8b9b06f6111853b442206&token=556705145&lang=zh_CN#rd*
本文由编辑推荐,原出处:https://www.eet-china.com/mp/a158367.html
人们总以为眼见为实,是的,这个实是以实体人自身的功能性能为条件的。未来虚拟人的眼界会不一样了?为什么?