在这篇文章,我介绍了基于逸宸电子开发的总线适配器来点亮LED灯的基本方法!
myastrotong:玩转GPIO之点灯(非树莓派)zhuanlan.zhihu.com这款总线适配器的介绍见这里:
工业级高速USB转SPI I2C PWM GPIO UART CAN接口电压可软件配置item.taobao.com没错,就是这个物件,一款USB转GPIO等常见接口的总线适配器,看上去牛皮的不得了。
学会了点灯,自然要挖掘一些高级点的玩法,以下是基于这个总线适配器点亮呼吸灯的玩法。
在很多需要调光的场合都采用PWM(脉冲调制)的方式调光(也称为“数字调光”),就是在固定流经LED的电流大小的情况下,通过占空比可调节的PWM脉冲来反复控制LED的导通和关断 。 导通的时候LED按照设定好的电流值发出相应亮度的光,关断的时候LED不亮。如果PWM脉冲的重复周期高于人眼视觉暂留需要的频率,特别是达到50Hz以上后,一般人眼就觉察不出LED的闪烁了,从而通过改变PWM脉冲的占空比就能够改变LED的亮度。
熄灭之前就又打开了,那么灯实际上是会维持在一个亮度的,或者你的眼睛看上去灯会维持在一个亮度。如果你一直保持某一个固定的频率,那么电灯就会保持一个固定的亮度。理论上,你可以通过调整开灯持续的时间长度和关灯持续的时间长度的比例,从而得到不同亮度。这个比例被称为“占空比”。
通过调整“占空比”就可以做到呼吸灯的效果。
准备硬件:一个三色信号灯(你也可以选择一个发光二极管和一个电阻,我这里仅仅是为了方便)、两根母对公杜邦线。
查询官方文档,总线适配器的各个GPIO的定义如下:
我选择接入PWM_CH3接口端(也就是P8端口)。白色杜邦线接入CH3接口和三色灯的G口,黄色杜邦线接入总线适配器的GND端和三色灯的GND端。
接好的效果图如下:
然后基于官方示例文件进行修改。修改examplespythonUSB2PWMUSB2PWM_Test下面的USB2PWM_Test.py文件:
from ctypes import *
import platform
from time import sleep
from usb_device import *
from usb2pwm import *if __name__ == '__main__': DevIndex = 0DevHandles = (c_int * 20)()# Scan deviceret = USB_ScanDevice(byref(DevHandles))if(ret == 0):print("No device connected!")exit()else:print("Have %d device connected!"%ret)# Open deviceret = USB_OpenDevice(DevHandles[DevIndex])if(bool(ret)):print("Open device success!")else:print("Open device faild!")exit()# Get device infomationUSB2XXXInfo = DEVICE_INFO()USB2XXXFunctionString = (c_char * 256)()ret = DEV_GetDeviceInfo(DevHandles[DevIndex],byref(USB2XXXInfo),byref(USB2XXXFunctionString))if(bool(ret)):print("USB2XXX device infomation:")print("--Firmware Name: %s"%bytes(USB2XXXInfo.FirmwareName).decode('ascii'))print("--Firmware Version: v%d.%d.%d"%((USB2XXXInfo.FirmwareVersion>>24)&0xFF,(USB2XXXInfo.FirmwareVersion>>16)&0xFF,USB2XXXInfo.FirmwareVersion&0xFFFF))print("--Hardware Version: v%d.%d.%d"%((USB2XXXInfo.HardwareVersion>>24)&0xFF,(USB2XXXInfo.HardwareVersion>>16)&0xFF,USB2XXXInfo.HardwareVersion&0xFFFF))print("--Build Date: %s"%bytes(USB2XXXInfo.BuildDate).decode('ascii'))print("--Serial Number: ",end='')for i in range(0, len(USB2XXXInfo.SerialNumber)):print("%08X"%USB2XXXInfo.SerialNumber[i],end='')print("")print("--Function String: %s"%bytes(USB2XXXFunctionString.value).decode('ascii'))else:print("Get device infomation faild!")exit()# Initialize adcPWMConfig = PWM_CONFIG()#我选的是P8,对应的PWM是CH3 二进制是1000 ->16进制是0x08PWMConfig.ChannelMask = 0x08for i in range(0,8):PWMConfig.Polarity[i] = 1 # 将所有PWM通道都设置为正极性for i in range(0,8):PWMConfig.Precision[i] = 100 # 将所有通道的占空比调节精度都设置为1%for i in range(0,8):PWMConfig.Prescaler[i] = 10 # 将所有通道的预分频器都设置为10,则PWM输出频率为200MHz/(PWMConfig.Precision*PWMConfig.Prescaler)for i in range(0,8):PWMConfig.Pulse[i] = PWMConfig.Precision[i]*30//100 # 将所有通道的占空比都设置为30%# 初始化PWMret = PWM_Init(DevHandles[DevIndex],byref(PWMConfig));if ret != PWM_SUCCESS:print("Initialize pwm faild!")exit()else:print("Initialize pwm sunccess!")print(DevHandles[DevIndex])# 启动PWM,RunTimeOfUs之后自动停止,利用该特性可以控制输出脉冲个数,脉冲个数=RunTimeOfUs*200/(PWMConfig.Precision*PWMConfig.Prescaler)#RunTimeOfUs=0,表示一直输出 RunTimeOfUs = 0ret = PWM_Start(DevHandles[DevIndex],PWMConfig.ChannelMask,RunTimeOfUs)if(ret != PWM_SUCCESS):print("Start pwm faild!")exit()else:print("Start pwm sunccess!")try:while (True):#改变PWM波形占空比 for j in range(0,101,2):for i in range(0,8):PWMConfig.Pulse[i] = j PWM_SetPulse(DevHandles[DevIndex],PWMConfig.ChannelMask,PWMConfig.Pulse)sleep(0.05) for j in range(100,-1,-2):for i in range(0,8):PWMConfig.Pulse[i] = j PWM_SetPulse(DevHandles[DevIndex],PWMConfig.ChannelMask,PWMConfig.Pulse) sleep(0.05) except KeyboardInterrupt:pass# 停止PWM# l、et = PWM_Stop(DevHandles[DevIndex],PWMConfig.ChannelMask)# if(ret != PWM_SUCCESS):# print("Stop pwm faild!");# exit()# else:# print("Stop pwm sunccess!")# Close deviceret = USB_CloseDevice(DevHandles[DevIndex])if(bool(ret)):print("Close device success!")else:print("Close device faild!")exit()
关键控制电路部分的代码为:
我选择的是CH03端口,所以对应的
PWMConfig.ChannelMask = 0x08
然后程序通过修改如下代码来改变占空比:
PWMConfig.Pulse[i] = j
并且先通过占空比增加,然后使占空比减小,从而得到呼吸灯暗亮的间歇变化。
效果视频如下:
点亮一盏呼吸灯https://www.zhihu.com/video/1224789136399835136以上就是通过PWM来点亮一盏呼吸灯的全部过程。