破解山东大学(威海)无线充电车模LED柱的闪烁之谜
Posted 卓晴
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了破解山东大学(威海)无线充电车模LED柱的闪烁之谜相关的知识,希望对你有一定的参考价值。
01 LED灯柱
1.1 背景介绍
在博文 线上比赛无线充电组仲裁申请以及检查结果 记录了第十七届智能车竞赛全国总决赛中山魂八队比赛受到参赛队伍质疑的问题。为何受到质疑,主要一个原因来自于网络直播比赛过程中,远程观看山魂八队车模显示电压的 LED 灯柱出现三个一排的点亮以及所发生的的突然变亮和变暗的情况。在 对于山东威海-无线充电组技术报告中的疑问及其回复 给出了山魂八队的技术报告及其相关质疑和回复。特别是技术报告中显示了山魂八队无线充电组 LED 灯柱的硬件 原理图以及循环点亮的程序算法。
那么,根据上面的技术资料,是否可以重现 LED 灯柱以及显示特性呢? 本文就搭建相应的实验电路进行测试。
▲ 图1.1.1 山大威海无线充电组现场测试过程
1.2 测试方案
由于只是测试山魂八队 LED 灯柱的显示特性,所以并不完全按照他们的硬件电路进行搭建,而是将其中的显示基本原理保持一致即可。 下面分别给出测试硬件和软件设计方案。
1.2.1 灯柱显示
根据 第十七届智能车竞赛技术报告-无线充电组-山东大学(威海) 可以知道他们将灯柱中的 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模块转接板设计与实现 。下面是将该接口板的原理图转帖过来。
▲ 图1.2.3 ESP32测试版接口图
(1)端口配置
使用其中GPIO32,33,35,26,27分别控制 LED 灯柱的行与列。实际上通过测试发现, ESP32 的所有 GPIO 中,并不是所有的 GPIO 都适合做输出端口,最终使用其中的 32,33,25,27,26 来驱动 LED 灯柱。
(2)软件编程
根据 MicroPython ESP32 编程文档,控制六个 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 摄像机观察结果
通过摄像机观察闪烁的灯柱, 可以看到LED灯柱亮度平稳,没有闪烁。这与人眼观察到的现象是相同的。
▲ 图1.3.1 通过摄像机观察到的LED灯柱亮度
1.3.2 通过手机观察结果
通过手机观察 LED 灯柱亮度,可以看到 LED 灯柱在闪烁。
▲ 图1.3.2 通过手机观察LED亮度变化
1.3.3 使用硬件中断
由于前面利用了软件延迟,所以 LED 闪烁的频率不是准确的 50Hz,下面利用 ESP32 的硬件时钟中断,产生更加准确的 50Hz 闪烁。
(1)实验程序
from machine import Pin,Timer
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()
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 使用HDMI接口的摄像头拍摄的LED亮度变化情况
1.3.4 分析结果
通过上面测试,可以看到 LED 灯柱如果采用高频闪烁的时候, 由于闪烁频率很高,由于视觉暂留现象,人眼看到是平均的亮度。 但是在手机摄像头中,可能观察到的是亮度闪烁的情况。这也解释了在比赛中远程观察到的 LED 灯柱呈现闪烁的情况。
02 比赛程序
为了说明比赛中山魂八队无线充电队 LED 灯柱的如下奇特现象:
- 观察到其 LED 灯柱似乎是三个一组同时点亮和熄灭;
- 在运行中会出现 LED 灯虚亮 的情况;
下面根据 第十七届智能车竞赛技术报告-无线充电组-山东大学(威海) 中给出的 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,Timer
import 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灯柱运行状况
下面是山大威海无线车模在对车模法拉电容放电过程,可以看到灯组的高压对应的 9 个 LED 是三个一组进行突然熄灭,最低压 3 个 LED 则是单个逐灯熄灭。从这一点来看, 他们的程序符合上面 MicroPython 复现主程序的逻辑过程。
▲ 图A2.1.3 山大威海无线充电车模放电过程
2.1.3 问题解决
(1)错误分析
上面错误来源于山大威海编程中的错误。 按照 LED 矩阵扫描原理,每一次只能够选择一个 MOS 管导通,但是按照前面论文中的程序,可以看到随着 voltage_light 增加, 导通的 MOS 管会逐步增多。这就会使得同时点亮的行之间相互干扰。 具体表现上就是除了第一行之外,其它各行的三个 LED 都是同时被点亮。
比如: 当变量 voltage_light 在 3 ~ 5 之间时, 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,与前面测试灯柱闪烁的频率一致。
2.2.1 不同摄像头下的闪烁
(1)摄像机下的图像
在摄像机下, 可以看到 LED 灯柱亮度是恒定的,看不出任何闪烁的情况。
▲ 图2.2.1 . 摄像机下LED灯柱亮度情况
(2)手机下的图像
使用手机拍摄 LED 灯柱,可以看到它的亮度出现非常明显的闪烁现象。
▲ 图2.2.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。 这种虚亮现象也就能回答在 线上比赛无线充电组仲裁申请以及检查结果 同学提示的疑问,也就是看到过 12 46 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 灯柱点亮的情况,已经彻底消除了 “虚亮” 的现象了。
▲ 图2.2.4 . 消除虚亮后摄像机拍摄到的LED灯柱情况
※ 总 结 ※
智能车竞赛山大威海无线充电队伍在远程比赛过程中,视频显示他们的 LED 灯柱出现的奇怪现象,包括有:(1) 三个 LED 同时点亮; (2) 出现 LED 虚亮的现象。 本文根据 山大威海提交的技术报告中的硬件和软件,使用自制 ESP32 电路板,利用 MicroPython 编程,测试了 LED 灯柱电路和控制软件。指出了山大威海技术报告中 LED灯柱控制软件存在的问题,并提出了修改办法。在一定程度上解释了远程比赛视频中出现的错误现象。 特别是虚亮现象,在现场人眼是不易觉察出,但通过摄像头捕捉之后就有可能显示出被超前点亮现象。这使得远程观看比赛视频中往往会出现显示的电压突变和虚高现象,从而引起围观的各种的猜疑。
比赛虽然结束了,但我们仍然忘不了其中的纷纷扰扰,争争执执。也许其中还有很多秘密我们还不知道,但行胜于言,通实验验数据验证猜测,将会让我们懂得更多,走得更远,也许这正是智能车竞赛令人着迷的地方吧。
人们总以为眼见为实, 有图有真相。但实际过程中,眼睛看到的未必是实际情况。下面一个动图是在推文 数码内外& 以上是关于破解山东大学(威海)无线充电车模LED柱的闪烁之谜的主要内容,如果未能解决你的问题,请参考以下文章