无限延伸镜子

一款基于 Arduino 和超声波传感器的无限延伸镜子。

Cherry

喜欢

11508
浏览
5
喜欢

> 更多图片

项目状态:已完成
开放度:公开
所属分类:电子
发布时间:2018-08-07
最近更新:2018-08-15

详细说明

这是一个非常有趣的项目,我花了一个周末来完成它。当把相框和LED灯条连起来之后,就可以用Arduino代码做出多变的炫酷特效。

我最初的想法是使用超声波传感器来感应镜子前面的运动,然后产生相应的LED移动特效。我将超声波传感器安装在相框的背面,但它们的精确度没有达到我的预期。但最终的版本运转起来也还不错!

另一个有趣的特效是相框的背面——固定支架连接到相框的方式,使其背部成一个小角度。这样,使镜子不是直视镜子,而是有一个微小的角度,所以产生了向下的无限延伸效果。整个制作花了几个小时,很有趣。让我们开始吧~

链接表


教程

组件清单
  • 相框 × 1
  • 窗玻璃UV贴膜 × 1
  • Arduino Uno × 1(或类似的Arduino芯片组)
  • LED灯条 × 若干(5V)
  • 超声波传感器 × 4
  • 排母 × 若干(可选)
  • 电容器 × 1 (大约100uF到220uF)
  • 电阻器 × 1 (大约200-600欧姆都可以工作)
  • 电池组 × 若干(9V电池)
  • 烙铁 × 1(也可使用压接机)
  • 热熔胶枪 × 1
  • 玻璃切割机 × 1
  • 连接线 × 1(CAT5)
  • Dupont压接机 × 1(可选,但非常实用)
  • 3D打印机 × 1

材料清单


相框×1
窗玻璃UV贴膜×1
Arduino Uno×1(或类似的Arduino芯片组)
LED灯条×若干(5V)
超声波传感器×4
排母×若干(可选)
电容器×1 (大约100uF到220uF)
电阻器×1 (大约200-600欧姆都可以工作)
电池组×若干(9V电池)
烙铁×1(可选)
热熔胶枪×1
玻璃切割机×1(如果需要切割镜子或玻璃)
连接线×1(CAT5)
Dupont压接机×1(可选,但非常实用)
3D打印机×1

相框要足够大,以便将LED灯条固定在里面,并为前面的玻璃和后面的镜子留出空间。

在玻璃上贴上UV贴膜

在前面的玻璃上贴上UV贴膜,形成“双向”镜面。

无限延伸镜的工作原理是:灯光会在后面的镜子和前面的“双向”镜子之间反射,视觉上不断地远离“双向”镜子,最后产生无限延伸的效果。

我使用的是银色的窗户UV贴膜,镜面效果非常不错。你也可以尝试不同的颜色,获得其他效果。

按照贴膜附带的说明操作,然后将其贴在前端玻璃的背面即可。我是这样处理贴膜的,首先我将肥皂水涂在玻璃上,再将贴膜切成精确的尺寸(或略小),贴在玻璃上并用刮刀挤出多余的水。让它在一夜之间干燥,你也可以这样试试。

安装LED灯条


测量相框的内部尺寸,并确定四个侧面中每个侧面需要多少个LED灯条。如果每侧LED灯的数量是奇数,将更方便。如果是奇数的LDE灯,就会有一个LED灯成为这一侧的中心。

一旦确定每侧需要多少个LED灯,请仔细切割LED灯条,确保只切割指定位置并保持最终切割部件的正确极性。

切割LED灯条后,将它们安装到相框中,并仔细测量需要多少连接线才能在角落中重新连接它们。

在LED灯条的起始位置焊接上一条用于连接 Arduino 的引线。所有引线都从后面的镜子穿出来。

在正确切割和焊接LED灯条之后,将LED灯粘贴到框架上,将它们安装在相框内部。在LED灯条的关键位置涂上热熔胶用于固定。需要特别注意相框的角落,因为那里容易松散。

为超声波传感器部署软件



将超声波传感器连接到这个项目的方法有很多种。我是通过将电线引线连接到母排的4个引脚上,然后将其头部用热熔胶粘到框架的背面。这样方便我随时插入或移除超声波传感器。

在每个排头上使用4条不同颜色的电线,并将顺序保持与相框周围完全相同。我们稍后将所有5V和GND线连接在一起,每组ECHO,TRIGG线连接到Ardiuno。在将电线焊接到接头之后,我在每个接头上添加了一小块收缩管。

或者,超声波传感器也可以直接焊接到电线上并安装在相框上。

安装镜子和背板


将超声波传感器头部粘合后,是时候将镜子粘贴到相框的背面并安装到位。如果你的镜子太大,请使用玻璃切割器将其切割成正确的尺寸。

我的相框是使用框架中的凹槽来固定背部,然后使用两个小金属钩将其固定到位,使我的背部略微倾斜。你的设计可能会有所不同。

使用热熔胶时,在背面涂上几大块胶水,然后将镜子安装到位。镜子粘合后,将电线绕在电线周围并将其连接到框架上。如有必要,在每个角落涂抹少量热熔胶。

在安装背板之前,最好先测试一下LED灯条,确保所有接线都正确无误。此外,确保在连接之前将LED线引线从背面拉出,因为我们的下一步将需要这些引线。

连接 Arduino 和超声波传感器





1、整理所有超声波传感器的GND线,并在将它们全部焊接在一起之前添加一节超软的导线。将导线插入 Arduino UNO。对所有超声波传感器的5V导线以类似的方式插入Arduino。

2、LED灯条的GND和5V自己需要一个100-200uF的电容。确保正确的极性,电容的负极在GND线上。我使用与传感器相同的线和技术将其焊接在一起。

3、在LED灯条的DATA线上,串联一个200-500欧姆的电阻。这将确保我们的LED灯带不会产生电流涌入,导致我们的第一个LED烧坏。在所有连接处添加热缩管。下一步显示电路图是否有用。

完成所有接线后,将每根线连接到Arduino。 GND接到GND,5V接到5V,LED数据接到PIN 10,传感器接到PIN 2-9。

我用压接器将杜邦线的尾部添加到每根电线上。如果你没有压接器,可以将连接线焊接到每根电线上或将它们焊接到插头引脚中。

电路图



这是我设计的电路图。看可能看起来很复杂,其实它只有4个传感器,每个传感器有4根电线,还有LED灯条。

Arduino 源代码


我选择在传感器周围制作一个带有脉冲LED的橙色中心点,用于测量最近的物体。当然,既然你都有了传感器和基本代码,你可以做一些完全不同的事情。

需要注意:
使用 Adafruit NeoPixel 库,确保安装正确。
传感器的确切顺序及它们的针脚顺序。
调整相框使用的总像素数。
根据需要调整颜色。
在代码中配置好“角”所在的位置,它们是盒子每一侧的中心点。

#include <Adafruit_NeoPixel.h>
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 top
      focusMoveTo = corners[0];
    } else if (left < top && left < bot && left < right) {
      // move to left
      focusMoveTo = corners[1];
    } else if (bot < top && bot < left && bot < right ) {
      // move to bot
      focusMoveTo = corners[2];
    } else if ( right < top && right < left && right < bot ) {
      // move to right
      focusMoveTo = 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; // to convert time into distance
                           //The speed of sound is 340m/s or 29 microseconds per centimeter. 
                           //the ping travels out and back so distance from the obstacle is half of the distance travelled
}

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);
}

3D打印支架和安装电池


由于背面的 Arduino 和电池不适合贴在墙上,所以我设计一个简单的3D打印支架。我的版本经过4次修改。底部配有超声波传感器的安装空间,同时可以紧紧固定相框。

将 Arduino 和电池组粘贴到框架的背面,完成!
最后,希望你喜欢这个项目,收集材料制作一套吧!