普通数码相机通过使用大量光传感器来捕获从物体反射的光。在这个实验中,我想看看我是否可以构建一个反向摄像头:我不用光传感器阵列,而是只有一个传感器;但是我用32 x 32 LED矩阵控制1,024个单独光源。
它的工作方式是Arduino一次点亮一个LED,同时使用模拟输入监视光传感器的变化。这允许Arduino测试传感器是否可以检测到特定的LED。对1,024个单独的LED中的每一个快速重复该过程,来生成可见的像素图。
如果在LED矩阵和传感器之间放置一个物体,Arduino就能捕捉到该物体的轮廓,一旦捕获完成,该物体的阴影将会显示出来。
奖励:通过微小的调整,相同的代码可实现在LED矩阵上绘画的“数字手写笔”。
第1步:此构建中使用的部件
对于这个项目,我使用了以下组件:
Arduino Uno与面包板
32x32 RGB LED矩阵(来自AdaFruit或Tindie)
5V 4A电源适配器(来自AdaFruit)
直流电源适配器2.1毫米插孔,螺丝接线端子(来自AdaFruit)
一个透明的3mm TIL78光电晶体管
AdaFruit还销售Arduino防护罩,可用于代替跳线。
由于我有一些Tindie积分,我从Tindie得到了矩阵,与AdaFruit的矩阵是相同的,所以任何一个都可以。
光电晶体管来自我几十年前的零件。它是一个3mm的TIL78。据我所知,该部件适用于红外线,是一个透明的外壳或一个阻挡可见光的黑暗外壳。由于RGB LED矩阵发出可见光,因此必须使用透明版。
这个TIL78似乎已经停产,但我想这个项目可以使用现代光电晶体管来制造。如果你发现有用的东西,请告诉我,我会更新这个项目!
第2步:接线并测试光电晶体管
通常情况下,您需要一个电阻与光电晶体管串联,但我知道Arduino能够在任何引脚上启用内部上拉电阻。我可以利用它将光电晶体管连接到Arduino,而无需任何额外的组件。
我用导线将光电晶体管连接到Arduino上的GND和A5引脚。然后我创建了一个例程代码,将A5引脚设置为INPUT_PULLUP。这通常是当开关使用的,但在这种情况下,它为光电晶体管提供电源!
此代码将值打印到对应的串行端口。通过使用Arduino IDE“工具”菜单中的便捷“串行绘图仪”,我可以获得环境光的强度图!当我用手盖住并打开光电晶体管时,图表会上下移动。
这个代码是检查光电晶体管极性接线是否正确的。
步骤3:将Matrix带状电缆连接到Arduino
为了将矩阵连接到Arduino,我浏览了Adafruit的这方面的指南。为方便起见,我将图表和引脚分布粘贴到文档中并打印了一个快速参考页面,以便在连接所有内容时使用。
请注意确保连接器上的选项卡与图中的选项卡匹配。
对于更简洁的电路,您可以使用AdaFruit连接RGB矩阵。可能需要焊接光电晶体管的插头或导线。
第4步:连接矩阵
我将矩阵电源线上的叉形端子拧到插孔适配器上,确保极性正确。由于部分端子暴露在外,为了安全起见,我用电工胶带包裹了整个部件。
然后,我插上电源连接器和电线,注意不要在过程中干扰跳线。
第5步:安装AdaFruit矩阵库并测试矩阵
您需要在Arduino IDE中安装“RGB矩阵面板”和AdaFruit“Adafruit GFX Library”。如果你需要帮助,这个教程是最好的方法。
我建议你运行一些例子,以确保你的RGB面板可以正常工作。我推荐“plasma_32x32”的例子!
重要提示:我发现如果在将5V电源插入矩阵之前我给Arduino上电,矩阵会变暗。似乎矩阵试图从Arduino中获取力量!所以为了避免Arduino过载,在启动Arduino之前要先给矩阵加电!
第6步:加载Matrix扫描代码.
现在,加载Arduino程序来对矩阵进行扫描。我提供了Arduino源代码。一旦你下载后,你应该看到闪烁的光每隔几秒扫一次矩阵。
如果将光电晶体管靠近矩阵,您应该看到光电传感器附近的LED亮起。
尝试进一步移动光电晶体管,使其更接近矩阵。如果您将一个物体放在矩阵上并将光电晶体管放在它上面,您应该能够捕获物体的“阴影”!
您可以在代码中调整一些参数:
如果检测不正常,您可以尝试增加READING_PER_PIXEL和THRESHOLD。将CLEAR设置为false其中每个新一轮的扫描都会向画布添加更多的线条。将INVERT设置为true,其中矩阵常亮,但光电晶体管会使其“阴影”部分变暗
第7步:代码的工作原理:检测可见光与遮挡的LED
经过一些实验,我发现检测传感器中是否可见像素的最佳方法,是从传感器获取成对的模拟读数:LED关闭时读取一个,LED打开时读取另一个读数。如果传感器看不到LED,则读数几乎相同;如果传感器可以看到LED,则读数会有所不同。
为了提高灵敏度,我使用OE(输出使能)线来打开和关闭LED,并读取多个读数。我使用两个累加器来统计LED关闭时的读数与LED打开时的读数。然后,我将这两个总和之间的差异与阈值进行比较,以确定该值是否超过某个阈值,从而让我决定LED是否在传感器的视线范围内。
第8步:代码的工作原理:扫描矩阵
为了扫描矩阵,我直接操作数据线,因为这比使用AdaFruit库绘制像素更有效。在开始扫描之前关闭中断,来禁用AdaFruit库。由于AdaFruit库通过使用中断来工作,这使我可以暂时控制矩阵。
矩阵具有六个移位寄存器,对应于矩阵的上半部和下半部中的整行像素的R,G,B颜色。还有一个锁存控制线(LAT),它将移位寄存器中的值复制到LED驱动器。四条地址线(A,B,C和D)选择上半部分和下半部分的有效行,OE(输出使能)用于打开和关闭LED驱动器。
在正常操作中,锁存器保持上一次点亮的行的值,同时新的值移位到移位寄存器中。加载完整行后,将锁定新值,并为下一行重复该过程。这种更新方式需要写入整行,即使只需要写入一个像素也是如此。
对于扫描,我选择利用移位寄存器,但不选择锁存功能。我将锁存控制线(LAT)设置为高电平,使得在每个CLK脉冲上,移位寄存器的内容立即加载到LED驱动器上。一旦我点亮了第一个像素,时钟线(CLK)上的每个脉冲都会使点亮的像素沿着行向下到下一个像素。通过这样做,就可以将点亮像素向下来扫描整行。
对于行中的每个位置,我使用OE(输出使能)线来打开和关闭像素,同时从光传感器获取读数。一旦我有足够的读数来确定该像素是否可见,我就会向AdaFruit库的帧缓冲区写一个颜色(扫描时,我仍然可以将像素值写入库的帧缓冲区,即使库暂时暂停) 。
扫描完所有行后。我重新启用中断,这会导致AdaFruit库使用缓冲区中的数据刷新矩阵,直到我准备好进行下一次扫描。