创客实战 | 用Arduino制作一款奇幻的“灯光隧道”
前言
前几期都是炫酷的LED作品,或简或难,而这期老外又把LED玩出了新花样:把相框和灯条组合,用Arduino作为中控制作一款奇幻的“灯光隧道”。这个作品的电路非常简单,初学者即可完成,可能相框和玻璃等材料需要麻烦一点,可以找商家定制。
作品的思路是用安装在相框背后的超声波传感器来感应镜子前方的运动,然后产生相应的LED显示特效。另外固定支架与相框呈一定角度,产生了无限延伸的效果。
视频先睹为快。
材料
1、Arduino ×1
2、LED灯条 ×若干(5V)
3、超声波传感器 ×4
4、排母 ×若干
5、电容 ×1 (大约100uF到220uF)
6、电阻 ×1 (大约200-600欧姆)
7、电池 ×若干(9V电池)
8、玻璃、镜子、UV贴膜和相框(可找商家定制)
相框要选择合适大小,因为要在里面固定LED灯条、在前面装上玻璃和在后面装上镜子。
步骤
在玻璃上贴上UV贴膜
“灯光隧道”原理:灯光会在后面的镜子和前面的“双向”镜子之间连续反射,视觉上不断地远离“双向”镜子,最后产生无限延伸的效果。
因此在前面的玻璃上贴上UV贴膜,形成“双向”镜面。
该作品使用的是银色的窗户UV贴膜,镜面效果非常不错,也可以尝试不同的颜色,可能会有意想不到的效果。
建议先将肥皂水涂在玻璃上,然后将贴膜切成合适的大小,贴到玻璃上后用一块小板刮出多余的水,放置一晚上干燥,这样贴膜效果会更好。
安装LED灯条
测量相框的内部尺寸,并确定四个侧面中每个侧面需要多少个LED灯条。建议每一侧安装奇数的LED灯,这样就可以有一个LED灯作为这一侧的中心,效果更棒。
确定每一侧需要多少个LED灯后,仔细切割LED灯条,要保证切割部位的正确极性,然后将它们安装到相框中,四个角的灯条两两相接。
在LED灯条的起始位置焊接一条连接 Arduino 的引线,所有引线都从后面的镜子穿出来。
切割和焊接LED灯条之后,将LED灯条粘贴到相框内部上,在LED灯条的关键位置用热熔胶固定。
安装超声波传感器
将电线连接到排母的4个引脚上,然后将其头部用热熔胶粘到框架的背面,这样方便随时插拔超声波传感器。
在每个排头上使用4条不同颜色的电线,顺序与相框周围完全相同,再将所有5V和GND连线,每组echo,triger引脚接到Ardiuno。再将电线焊接到接头后,在每个接头上添加一小块收缩管。
安装镜子和背板
将超声波传感器头部粘好后,再将镜子安装到相框背面。该作品定制的相框是使用凹槽来固定背部,然后用两个小金属钩将其固定,使背部略微倾斜,不同的相框设计可能会有所不同,按实际情况来安装。
镜子安装完后,将电线接好,在每个角落用热熔胶固定。
在安装背板之前最好先测试一下LED灯条,确保所有接线都正确无误。另外,确保将LED引线从背面拉出,因为下一步需要用到这些引线。
Arduino 与超声波传感器接线
1、整理所有超声波传感器GND电线,连接到Arduino的GND,同理连接好5V。
2、LED灯条的GND和5V需要一个100-200uF的电容。为确保正确的极性,电容负极应接在GND上。
3、在LED灯条的DATA线上,串联一个200-500欧姆的电阻,避免电流过大使LED烧坏,在所有连接处最好使用热缩管。
完成所有接线后,将每根线连接到Arduino,GND接到GND,5V接到5V,LED数据引脚接到Arduino引脚10,传感器接到引脚2-9。
电路图
这是老外手画的电路图,看起来可能有点乱,其实电路非常简单,核心就是超声波和灯条的接线。
Arduino 代码
在传感器周围设置一个带有脉冲LED的橙色中心点,用于测量最近的物体,当然这只是一个点缀,你也可以按照自己的想法来。
#include const int NUMPIXELS = 26;Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, 10);const int NUMPIXELS = 26;Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, 10);const int topTrigPin = 2;const int topEchoPin = 3;const int leftTrigPin = 4;const int leftEchoPin = 5;const int botTrigPin = 6;const int botEchoPin = 7;const int rightTrigPin = 8;const int rightEchoPin = 9;void setup() {Serial.begin(9600);pixels.begin();}int corners[4] = {16, 23, 3, 10};int focusPoint = 20;int focusMoveTo = 20;int rainbow = 0;uint32_t rainbowColor = Wheel(0);unsigned long previousMillis = 0;void loop() {unsigned long currentMillis = millis();if (currentMillis - previousMillis >= 500) {previousMillis = currentMillis;long top = readSensor(topTrigPin, topEchoPin);long left = readSensor(leftTrigPin, leftEchoPin);long bot = readSensor(botTrigPin, botEchoPin);long right = readSensor(rightTrigPin, rightEchoPin);Serial.print("t:");Serial.print(top);Serial.print("l:");Serial.print(left);Serial.print("b:");Serial.print(bot);Serial.print("r:");Serial.println(right);rainbowColor = (Wheel((rainbow) & 255));rainbow = (rainbow + 1) % 255;if (top < left && top < bot && top < right ) {// move to topfocusMoveTo = corners[0];} else if (left < top && left < bot && left < right) {// move to leftfocusMoveTo = corners[1];} else if (bot < top && bot < left && bot < right ) {// move to botfocusMoveTo = corners[2];} else if ( right < top && right < left && right < bot ) {// move to rightfocusMoveTo = corners[3];}}if (focusPoint != focusMoveTo) {if (focusPoint > focusMoveTo) {focusPoint--;} else {focusPoint++;}}bounceAround(focusPoint);delay(30);}int pos = 0;long readSensor(int trigPin, int echoPin) {pos++;if (pos == 5) {pos = 0;}return pos;pinMode(trigPin, OUTPUT);pinMode(echoPin, INPUT);long duration, cm;digitalWrite(trigPin, LOW);delayMicroseconds(2);digitalWrite(trigPin, HIGH);delayMicroseconds(10);digitalWrite(trigPin, LOW);duration = pulseIn(echoPin, HIGH);return microsecondsToCentimeters(duration);}long microsecondsToCentimeters(long microseconds) { return microseconds/29/2; }int bounceSize = 5;int bounceSizeMax = 5;int bounceDirection = 1;void bounceAround(int point) {setAll(rainbowColor);if (bounceSize <= 0) {bounceDirection = 1;} if (bounceSize >= bounceSizeMax) {bounceDirection = -1;}bounceSize += bounceDirection;pixels.setPixelColor(point, pixels.Color(0,250,0));for(int i = 1; i <= bounceSize; i++ ){pixels.setPixelColor(point - i, pixels.Color(40*i,40*i,40*i));pixels.setPixelColor(point + i, pixels.Color(40*i,40*i,40*i));}showStrip();}void showStrip() {pixels.show();}void setAll(uint32_t color) {for(int i = 0; i < NUMPIXELS; i++ ) {pixels.setPixelColor(i, color);}}void setAll(byte red, byte green, byte blue) {for(int i = 0; i < NUMPIXELS; i++ ) {pixels.setPixelColor(i, red, green, blue);}}// Input a value 0 to 255 to get a color value.// The colours are a transition r - g - b - back to r.uint32_t Wheel(byte WheelPos) {WheelPos = 255 - WheelPos;if(WheelPos < 85) {return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);}if(WheelPos < 170) {WheelPos -= 85;return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);}WheelPos -= 170;return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);}--end--
声明:本文章由网友投稿作为教育分享用途,如有侵权原作者可通过邮件及时和我们联系删除:freemanzk@qq.com