像素地球仪
1. 项目背景
      视觉持久性(POV)是眼睛看到快速移动的物体,在不同时间将物体的位置拼接成单个有凝聚力的图像的现象。CRT显示器利用了这种现象,它使用光栅扫描法在每条水平扫描线中绘制单个像素,然后再返回到下一条扫描线的开头。我们构建了一个球形显示器,通过快速交替每列 LED 像素显示的颜色来创建图像。每列垂直像素同时显示。然后,在显示后续垂直扫描线之前,光源的物理位置移动一小段距离。
 
      我们的设备由一个安装在亚克力环上的60像素的 LED 灯条组成,该灯条内衬着一个运行 LED 像素阵列的60像素 LED 灯条。其底部安装在带有编码器的6V直流电机上,编码器使用霍尔效应传感器准确确定其位置。电机的转速设置为500 rpm。Adafruit的6线滑环使我们能够将固定框架的LED电源、时钟和数据线连接到旋转的亚克力环上。
设备的框架主体是用废木头建造的。承载LED的环状物直径为12英寸,由1/4英寸厚的亚克力激光切割而成。来自Adafruit的60个APA102 LED(条带密度为144 LED / m)用CA胶连接到环上。环的顶部和底部都夹在两个3D打印耦合器之间,耦合器由孔组成。主要用用于连接四个LED线和固定螺钉。
 
      电机被安装在一个正方形废木头内,木头被固定在框架的底部,带有四个金属支架。电机粘在木制方块上。电机底部木板被钻出,以便可以设置更深的内部。但电机本身实际上不能紧贴在木板内,因为底部的易碎编码器需要能够自由旋转。此外,电机的 500 RPM 转速会产生很多可怕的振动,因此我们在框架顶部添加了一点阻尼;因此,在操作设备的图片中可以看到类似于砖块的重量。
我们的设备的电子组件包括Raspberry Pi封装和μMudd Altera Cyclone IV开发板。每个控制器单独负责相应的封装子系统:Raspberry Pi控制LED灯条、μMudd板控制直流电机。控制板用作永久性试验板充当了电源硬件、电平转换器、Pi和FPGA上数字线路之间的桥梁。来自ATX计算机电源的5V和12V为灯、电流和电机供电。
      Raspberry Pi将3.3V 数据发送到电平转换器,电平转换器将 5V  SCL 和 SDA 线发送到 LED灯条。它还将两条线的数据发送到FPGA,实现“电机切换”和“复位”。控制板上的+5V和GND输入线被拼接到microUSB电缆中,为Raspberry Pi供电。FPGA从Raspberry Pi接收控制线。还将 3.3V 电压从稳压器发送到直流电机上的编码器。
      它从电机轮询两条编码器线。电机由 12V 电源轨供电。其低端由功率BJT驱动,其基极由FPGA电机控制引脚驱动。重要提示:电机的额定电压仅为 6 伏,因此电机控制 Verilog 的占空比上限为 75%,或等效输入电压为 9V。这仍然是一个过量电压,但不太严重。尽管如此,我们在电机低侧的功率BJT仍然会非常迅速地变得非常热。未来的设计将对此进行修改。
 
      开关在切换时将计算机电源上的PS_ON“绿色”导轨接地。这为整个系统提供了方便的开/关,切换电机、LED、树莓派和 FPGA。
2. FPGA
      FPGA子系统的目的是以所需的速度运行电机,且保持很小的偏差。如果实际旋转速率与假定的旋转速率不同,图像会在球体上产生偏移。FPGA系统通过从电机编码器获取输入,通过控制环路运行该数据,然后使用PWM信号驱动电机,其占空比由控制环路产生,从而产生稳定的旋转速率。在硬件中,这3个任务中的每一个都由一个单独的模块完成。
3. read_encoder
      该模块负责读取编码器数据。编码器发出一个方波,电机每转一圈12个循环周期。硬件模块将编码器信号通过同步器使所有边沿与时钟边沿对齐。项目采用了32位计数器,计数器可以实现在同步编码器信号的基础上复位,且每次复位时输出计数器值。这为我们提供了编码器波的周期,它代表了电机旋转的1/24,以FPGA时钟周期为单位。
 
4. control_loop
      该模块是FPGA子系统的大脑。控制环路从read_encoder获取周期数据,并使用稍作修改的PI控制环路为PWM模块产生占空比。标准PI控制环路在现有电流和所需输出电流之间产生了误差线性组合。我们的设备在旋转环时遇到了积分项问题。因为我们处理的是周期,所以在环旋转期间,我们有一个非常大的输出值。它太大了,以至于在积分项中引起了巨大的超调,然后溢出。这导致环旋转到了全功率,之后下降到更慢的速度,然后随着积分项溢出,最终稳定在正确的速度。
 
      我们不能只删除积分项,因为我们需要使用它来消除我们的稳态误差。相反,我们决定只允许积分项在循环以接近所需速度旋转时累积。这允许循环使用比例控制旋转,而不会累积和溢出我们的积分项,然后使用 PI 控制稳定在所需的数值。
 
      控制回路模块也以慢时钟运行。这是因为FPGA时钟以40MHz运行,但是当以我们期望的速度运行时,我们只能从编码器以大约1kHz的频率获得新数据。如果我们不减缓时钟,我们的整合项会积累得太快,并导致电机运行速度振荡以及溢出。我们的控制环路时钟以大约4kHz的频率运行,可以消除溢出的危险,也可以从编码器可靠地读取数据。
 
5. 脉宽调制
      PWM模块将占空比作为输入并生成相应的PWM信号。这是一个参数化模块,具有可变占空比分辨率和时钟分度。包含时钟分频参数,以便我们可以设置 PWM 频率。该模块根据分度生成较慢的时钟来产生PWM波。为了产生PWM波,我们有一个与占空比位数相同的计数器。一旦占空比和计数器匹配,我们就会降低输出,每次计数器复位时输出都会升高。这会产生一个在任意频率下具有正确占空比的方波。
 
6. LED控制
      APA102芯片组依赖于5V电路,因此需要使用74ACHT125四通道逻辑电平转换器将时钟和数据线从Pi到LED灯条从5.3V拉到3V。此外,在LED电源线上使用一个1000μF电容,来舒缓LED极快变化的电气负载。
 
      APA102通过通用SPI进行通信。支持极快的数据输入,我们目前以1 MHz 运行它。灯条中的每个LED都需要一个32 位“帧”数据:三个起始位、五个亮度控制位和 8 位蓝色、绿色和红色数据。一旦 APA102 器收到32位起始帧0x00000000,器件就开始读取 LED 帧。每个 LED 都有一个集成控制器,该控制器读取自己的颜色数据,然后将字符串其余部分的颜色数据输出到下一个 LED。
 
      主 C 程序最初通过调通“复位”FPGA 引脚(编号 27),然后打开“使能电机”FPGA 引脚(编号 22)来启用电机。然后它进入“热回路”,将数据写出到LED,直到中断。C 信号处理程序用于在程序中断时关闭电机和所有 LED。
 
      为了存储 LED 数据,我们需要创建一个数据结构。为此,我们首先为一个像素定义一个 C 结构,其中包含1个红色、绿色和蓝色的无符号字符值。然后,我们用C实现一个3D数组,这个数组将像素值存储在内存块中,大小为 (条带中的像素) * (图像中的像素列) *(动画中的帧)。getPixel() 方法返回指定3D数组中某个(x, y, z) 位置的像素指针,其中 (x,y) 描述其在显示图像中的垂直和水平位置,(z) 描述相关像素的帧号。
 
      在热回路中,Pi 通过 SPI 将数据写出到 LED 引脚,然后在增加要显示的垂直 LED 值之间休眠一个“延迟期”。“延迟周期”(以微秒为单位)由以下公式计算:
 
      延迟 = (1000000 * 60) / (像素列 * RPM)
 
      到达最后一列像素后,我们将重置为第一列像素。如果我们的像素动画中有多个帧,我们将恢复到后续动画帧的第一列。如果此重置每转恰好发生一次,我们的时机是完美的。
 
      为了正确安排LED框架的变化时间,需要考虑许多因素。首先,我们没有使用内置在提供的easyPIO.h方法的delayMicros()方法,而是编写了一个自定义方法,该方法返回Raspberry Pi的计时器寄存器中的值。在热循环开始时,我们轮询SPI定时器寄存器。最后(在写出SPI数据之后),我们检查所需的时间是否已经过去。在定时器寄存器指示所需时间已过之前,我们不会重复循环。这优于delayMicros() 方法,因为它考虑通过 SPI 发送数据所需的时间来减少延迟。
 
      最后,在将像素数据发送到LED之前,应使用简单的伽马校正功能,将每个颜色值立方映射,以提高颜色对比度和准确性。
 
7. 编辑器
为了更改球体所呈现出的内容,需要一个可以将内容保存到文件中的程序。因此,项目将.led 文件格式定义为以下特征。
 
4 字节标头,由以下值组成:
 
第1个字节:一列中的垂直像素数。(x轴)
 
第2个字节:图像中的水平像素数。(y轴)
 
第3个字节:在移动到下一个动画之前保存一个动画的帧数。
 
第4字节:动画中的帧数。(z轴)
 
4 个空字节(以防将来的文件想要在标头中存储额外的内容)
 
LED 数据存储在通用 3D C 阵列中 - 3*x 字节的 y 列的 z 帧
 
使用编辑器 (write_file.c) 读取或写入.led 文件可初始化这四个常量,并根据其值为 LED 数据分配内存。使用此编辑器打开.led文件还允许用户完成以下功能,这些功能是创建动画或静止图像所必需的:
 
在LED矩阵和动画帧之间移动光标;手动设置颜色值
 
增加单个像素的红色、绿色、蓝色通道
 
将像素颜色值复制并粘贴到其他像素上
 
清除像素
 
向上/向下/向左/向右移动整个图像
 
复制和粘贴整个帧
 
保存洋葱皮模式(上一帧叠加在当前帧之上)。
 
写出到 .led 文件
 
文件编辑器在 ncurses 中实现,ncurses 是构建图形命令行应用程序通用框架
8. 转换图像
      Python 库 PIL 用于将图像从任何标准文件格式转换为像素地球兼容的颜色数据数组。一个简单的循环由 20 多行代码组成,循环遍历输入图像中的每一行和每一列像素,并将颜色值输出为“无符号字符”值,然后将它们写入由用户指定名称的.led 文件。
 
      做这些工作前需要进行一些预处理以确保图像转换器正确完成工作。要绘制的图片必须渲染到60像素,以确保它显示在正确数量的 LED 上。此外,通过实验,我们可以确定,在500 rpm时,宽度约 130像素的图像将导致地球上的像素看起来具有相等的宽度和高度。从美学上讲,增加图像中的对比度也很有帮助。
 
2024-04-12
浏览77
🔧 DIY案例分享
登录后评论
评论
分享