Lightbox II 三轴加速度传感器与RGBLED

时隔半年,本学渣终于把lightbox二代憋出来了。

先看看lightbox II是个什么东西吧!

 

Lightbox II以Arduino Nano为核心,通过三轴加速度传感器ADXL345收集数据,用以选择功能和控制20只共阳级雾状RGBled。不可拆卸,但可以通过无线充电的方式进行充电。

其功能如下:1、在X轴方向摇动   –白光模式

                         2、在Y轴方向摇动    –自变色

                         3、在Z轴方向摇动    –随姿态变色

 

由于器件在内部的姿态问题,这里的XYZ跟程序的XYZ是不同的,但无关痛痒。
由于器件在内部的摆放姿态问题,整体的XYZ跟程序的XYZ方向可能是不同的,但这无关痛痒。

现在进入正题!

工具:1、电烙铁;2、热熔胶枪;3、裁剪万用板的工具。

材料:

Arduino Nano                           x 1

ADXL345                                   x 1

无线充电模块                           x 1

DC-DC 5V升压模块                x 1

3.7V锂离子电池952240        x 2

共阳极雾状RGBled               x 20

电阻5欧姆、100欧姆各1个

NPN型晶体管8050                x 3

杜邦线、针线、维修用飞线若干

5.5mmDC电源接口(圆口)x 1

12VDC电源适配器                 x 1

 

 

一、电路连接

总体原理图

R1的值取决于RGBLED的数量和型号,R2为100欧姆。
R1的值取决于RGBLED的数量和型号,这里R1为5欧姆,R2为100欧姆。
ADXL345模块,也有可能不是这个样子的。
ADXL345模块,也有可能不是这个样子的。
锂电池,并联起来。
锂电池,并联起来。某宝中顺电池【这不是广告!】
RGBled这里使用10mm高的。
RGBled这里使用10mm高的。
直径0.1mm飞线,每根只能允许流通47mA以下的电流。
直径0.1mm飞线,每根只能允许流通47mA以下的电流。
Arduino Nano
Arduino Nano
无线充电模块,某宝有售。链接http://item.taobao.com/item.htm?spm=a1z09.2.9.28.ZOivgQ&id=38592014875&_u=91jgd807a278 【不是广告啊!】
无线充电模块,某宝有售。链接http://item.taobao.com/item.htm?spm=a1z09.2.9.28.ZOivgQ&id=38592014875&_u=91jgd807a278 【真的不是广告啊!】
DC-DC升压模块,某宝育松有售。
DC-DC升压模块,某宝育松有售。

按照原理图连接或者焊接各个部分

一开始我用两组三极管,后来改为一组。
一开始我用两组三极管,后来改为一组。
测试中。别急,程序后面给。
测试中。别急,程序后面给。                 Arduino Nano的表面覆盖一层热熔胶,用来防止模块间接触造成以外的短路,其他器件也要这样做!
然后简单粗暴地用热熔胶将它们捆起来。捆起来之前可以剪掉器件上的一些针脚,以减小体积,比如arduino Nano的ICSP针脚。一旦作品完成这块Nano是不可能再拿出来用的了,所以,对于没用的i/o口针脚,该剪就剪。
然后简单粗暴地用热熔胶将它们捆起来。捆起来之前可以剪掉器件上的一些针脚,以减小体积,比如arduino Nano的ICSP针脚。一旦作品完成,这块Nano是不可能再拿出来用的了,所以,对于没用的i/o口针脚,该剪就剪。
IMG_20140910_181537
请无视我的脚吧QAQ

烧录好程序,测试功能,测试充电效果。做完以上工作之后,这块东西就可以先放在一边了。

 

 

二、亚克力和RGBled部分

【点击此处下载lightbox II的CAD图(dwg格式)】如果没有加工设备,可以直接发图给淘宝的店家加工,这里默认亚克力板的厚度为1.7mm。

下载本文的附件,在淘宝搜索“亚克力加工 激光”搜索到相关店家,联系客服,选好合适的亚克力板材(标称2mm,实际1.7mm),名称为《lightbox II(外)》的文件要切双面透明磨砂的亚克力,另外两个文件切不透明的材料,颜色自选,发送dwg文件给客服,确认无误后下单即可。

ATTENTION:
        【水深!对于价格一定要货比三家!同时要确认板材实际厚度为1.7mm!】

 

拿到亚克力后,找到5块有洞的亚克力片,仔细对比尺寸确认他们的位置关系,然后把RGBled装上去。

 

20个LED是并联的,安装的时候元件引脚穿过亚克力板上面的孔,注意引脚极性,不要接错。
20个LED是并联的,安装的时候元件引脚穿过亚克力板上面的孔,注意引脚极性,不要接错。

 

焊接细节。建议不要使用图中彩色的线,其实就是杜邦线剪成一段一段,这样的话焊点容易脱落。 柔软的维修用飞线是很好的选择,能够适应将亚克力围成长方体的过程。但是要注意,单根线的电流只允许在47mA以下,所以更靠近电源的地方要更多的线来连接,阳极引脚间的飞线也要比阴极引脚的多。焊接的时候要注意确认飞线不容易脱落,以及使用万用表确认是否导通。
焊接细节。建议不要使用图中彩色的线,其实就是杜邦线剪成一段一段,这样的话焊点容易脱落。
柔软的维修用飞线是很好的选择,能够适应将亚克力围成长方体的过程。但是要注意,单根线的电流只允许在47mA以下,所以更靠近电源的地方要更多的线来连接,阳极引脚间的飞线也要比阴极引脚的多。焊接的时候要注意确认飞线不容易脱落,以及使用万用表确认是否导通。

没错,这一步非常麻烦。

正面的效果
正面的效果
接上主要电路,也就是本文上一部分教大家做的电路。然后就围成长方体。
接上主要电路,也就是本文上一部分教大家做的电路。然后就围成长方体。
板间用可靠的胶水封好。
板间用可靠的胶水封好。内部部分就做好了。
底部再装上一块白色的亚克力,充电接收线圈粘在内部正中心,自锁开关的位置如图,要反复比较确认自锁开关的位置。
底部再装上一块白色的亚克力,充电接收线圈粘在内部正中心,自锁开关的位置如图,要反复比较确认自锁开关的位置。

mark透明磨砂的亚克力围成正方体外壳

透明磨砂的亚克力围成正方体外壳,装上内部部分,胶水固定。 作者发现502胶水会挥发,在接触面附近再凝结成雾状,有些影响外观。不知道大家有没有好的胶水推荐?
装上内部部分,胶水固定。
作者发现502胶水会挥发,在接触面附近再凝结成雾状,有些影响外观。不知道大家有没有好的胶水推荐?

 

·
最后的尺寸应该是96*96*96mm

三、充电座

充电座非常简单,就是几块亚克力把DC电源接头和无线充电模块的发射模块包在里面而已。

DC接口和无线充电模块的正负极接好就可以了。 大家还可以加上自锁开关和指示灯,加自锁开关记得改CAD图开孔。
DC接口和无线充电模块的正负极接好就可以了。
大家还可以加上自锁开关和指示灯,加自锁开关记得改CAD图开孔。
插好电,把lightbox II放上去,两个线圈对准就可以充电了。
插好电,把lightbox II放上去,两个线圈对准就可以充电了。

 

四、程序

在这里要先感谢极客工坊的弘毅,Lightbox II的ADXL345程序改自该贴http://www.geek-workshop.com/thread-80-1-1.html

还要感谢arduino.cn的各位大大,论坛里的大神@奈何col 编写的《Arduino程序设计基础》让我快速地入门了Arduino

I2C库的使用方法参见 宜昌城老张 的博客http://www.eefocus.com/zhang700309/blog/12-01/236815_59f78.html

定时器2库的使用方法参见http://www.arduino.cn/forum.php?mod=viewthread&tid=2890

#include <MsTimer2.h>               //调用定时器库
#include <Wire.h>                   
#define Register_ID 0
#define Register_2D 0x2D
#define Register_X0 0x32
#define Register_X1 0x33
#define Register_Y0 0x34
#define Register_Y1 0x35
#define Register_Z0 0x36
#define Register_Z1 0x37

int ADXAddress = 0xA7 >> 1;         
//存储加速度信息的变量
int X0, X1, Xg;   
int Y0, Y1, Yg;
int Z1, Z0, Zg;
//三种颜色对应的引脚
int ledx = 9;
int ledy = 5;
int ledz = 6;
//声明7个计数器
int counterX, counterY, counterZ, counterT, counterx, countery, counterz;
//3个记录状态的变量
int stateX, stateY, stateZ;
//自变色状态下三种颜色的初始强度(相当于3个呼吸灯)
int valx = 60;
int valy = 130;
int valz = 195;
//自变色状态下三种颜色的变化速度
int fadeAmount1 = 3;
int fadeAmount2 = 6;
int fadeAmount3 = 9;

void setup() {
  //  Serial.begin(9600);     //可以启动串口程序方便调试
  // 各项初始化
  Wire.begin();
  delay(10);
  Wire.beginTransmission(ADXAddress);
  Wire.write(Register_2D);
  Wire.write(8);
  Wire.endTransmission();
  pinMode(ledx, OUTPUT);
  pinMode(ledy, OUTPUT);
  pinMode(ledz, OUTPUT);

  counterY = 0;
  counterX = 0;
  counterT = 0;
  //X,Y,Z轴触发的状态均为关闭状态
  stateX = 0;
  stateY = 0;
  stateZ = 0;
}

void loop() {
  //全部熄灭
  digitalWrite(ledx, 0);
  digitalWrite(ledy, 0);
  digitalWrite(ledz, 0);
  
  //开始读取X,Y,Z轴加速度
  Wire.beginTransmission(ADXAddress);
  Wire.write(Register_X0);
  Wire.write(Register_X1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress, 2);
  if (Wire.available() <= 2);
  {
    X0 = Wire.read();
    X1 = Wire.read();
    X1 = X1 << 8;
    Xg = X0 + X1;
  }

  Wire.beginTransmission(ADXAddress);
  Wire.write(Register_Y0);
  Wire.write(Register_Y1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress, 2);
  if (Wire.available() <= 2);
  {
    Y0 = Wire.read();
    Y1 = Wire.read();
    Y1 = Y1 << 8;
    Yg = Y0 + Y1;
  }

  Wire.beginTransmission(ADXAddress);
  Wire.write(Register_Z0);
  Wire.write(Register_Z1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress, 2);
  if (Wire.available() <= 2);
  {
    Z0 = Wire.read();
    Z1 = Wire.read();
    Z1 = Z1 << 8;
    Zg = Z0 + Z1;  
  }   
  //判断X轴上的加速度是否到达阈值,到达则计数器X自加
  if (Xg >= 500 || Xg <= -500) {                                                      
    counterX++; 
    //如果计数器X开始计数,那么计时器开始计时,0.5秒后进入清零函数
    if (counterX == 1) {  
       MsTimer2::set(500, Clear); 
       MsTimer2::start();    
   } 
  } 
  //如果在进入清零函数之前计数达到16以上,就打开X轴触发的状态(进入自变色状态)
  if (counterX >= 16) {       //16可改为其他数字,数字越小灵敏度越高
    stateX = !stateX;
    while (stateX == 1) {
      fading();
    }
  }

  if (Yg >= 500 || Yg <= -500) {                               
     //  checking Y     
     counterY++; 
     if (counterY == 1) {  
        MsTimer2::set(500, Clear); 
        MsTimer2::start(); 
    } 
  } 

  if (counterY >= 16) {
    stateY = !stateY;
    while (stateY == 1) {
      following();
    }
  }

  if (Zg >= 500 || Zg <= -500) {                               
      //  checking Z     
      counterZ++; 
      if (counterZ == 1) { 
         MsTimer2::set(500, Clear); 
         MsTimer2::start(); 
    }
  } 

  if (counterZ >= 14) {
    stateZ = !stateZ;
    while (stateZ == 1) {
      white();
    }
  }
  delay(6);

  //  Serial.print("X=");
  //  Serial.print(Xg);
  //  Serial.print("  Y=");
  //  Serial.print(Yg);
  //  Serial.print("  Z=");
  //  Serial.print(Zg);
  //  Serial.print("  CX=");
  //  Serial.print(counterX);
  //  Serial.print("  CY=");
  //  Serial.print(counterY);
  //  Serial.print("  CZ=");
  //  Serial.println(counterZ);
}

void Clear() {                                                                   
  //所有的计数器清零
  counterX = 0;
  counterx = 0;
  counterY = 0;
  countery = 0;
  counterZ = 0;
  counterz = 0;
}

void white() {                                                                   
  //白光程序
  digitalWrite(ledx, 1);
  digitalWrite(ledy, 1);
  digitalWrite(ledz, 1);
  
  //读取Z轴上的加速度
  Wire.beginTransmission(ADXAddress);
  Wire.write(Register_Z0);
  Wire.write(Register_Z1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress, 2);
  if (Wire.available() <= 2);
  {
    Z0 = Wire.read();
    Z1 = Wire.read();
    Z1 = Z1 << 8;
    Zg = Z0 + Z1;
  }
  if (Zg >= 500 || Zg <= -500) {
     counterz++;
     if (counterz == 1) {
       MsTimer2::set(500, Clear);
       MsTimer2::start();
     }
   }
  //如果计数器Z计数达到140以上,就关闭Z轴触发的状态,回到主程序
  if (counterz >= 140) {
    stateZ = !stateZ;
    return;
  }

  //  Serial.print("Z=");
  //  Serial.print(Zg);
  //  Serial.print("  CZ=");
  //  Serial.println(counterz);

}

void following() {                                                               
  //跟随姿态变色的程序

  int xfollow, yfollow, zfollow;

  Wire.beginTransmission(ADXAddress);
  Wire.write(Register_X0);
  Wire.write(Register_X1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress, 2);
  if (Wire.available() <= 2);
  {
    X0 = Wire.read();
    X1 = Wire.read();
    X1 = X1 << 8;
    Xg = X0 + X1;
  }

  Wire.beginTransmission(ADXAddress);
  Wire.write(Register_Y0);
  Wire.write(Register_Y1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress, 2);
  if (Wire.available() <= 2);
  {
    Y0 = Wire.read();
    Y1 = Wire.read();
    Y1 = Y1 << 8;
    Yg = Y0 + Y1;
  }

  Wire.beginTransmission(ADXAddress);
  Wire.write(Register_Z0);
  Wire.write(Register_Z1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress, 2);
  if (Wire.available() <= 2);
  {
    Z0 = Wire.read();
    Z1 = Wire.read();
    Z1 = Z1 << 8;
    Zg = Z0 + Z1;
   }
   //限定X,Z轴的数值,避免出现颜色的跳变,Y轴由于要留作退出程序的判断所以不限定
   Xg = constrain(Xg, -272, 272);
   //  Yg = constrain(Yg, -272, 272);
   Zg = constrain(Zg, -272, 272);
   xfollow = map(Xg, -272, 272, 5, 250);
   analogWrite(ledx, xfollow);
   yfollow = map(Yg, -290, 290, 5, 250);
   analogWrite(ledy, yfollow);
   zfollow = map(Zg, -272, 272, 5, 250);
   analogWrite(ledz, zfollow);
   
   //防止溢出产生的颜色跳变
   xfollow = constrain(xfollow, 1, 255);
   yfollow = constrain(yfollow, 1, 255);
   zfollow = constrain(zfollow, 1, 255);

   if (Yg >= 500 || Yg <= -500) {
     countery++;
     if (countery == 1) {
       MsTimer2::set(500, Clear);
       MsTimer2::start();
     }
   }

   if (countery >= 40 ) {
    stateY = !stateY;
    return;
   }
  //  Serial.print("Y=");
  //  Serial.print(Yg);
  //  Serial.print("  CY=");
  //  Serial.println(countery);

}

void fading() {                                                                
  //自变色函数

  analogWrite(ledx, valx);
  analogWrite(ledy, valy);
  analogWrite(ledz, valz);


  valx = valx + fadeAmount1;
  valy = valy + fadeAmount2;
  valz = valz + fadeAmount3;


  if (valx <= 4 || valx >= 252) {
    fadeAmount1 = -fadeAmount1 ;
  }
  if (valy <= 7 || valy >= 249) {
    fadeAmount2 = -fadeAmount2 ;
  }
  if (valz <= 10 || valz >= 246) {
    fadeAmount3 = -fadeAmount3 ;
  }

  delay(90);

  Wire.beginTransmission(ADXAddress);
  Wire.write(Register_X0);
  Wire.write(Register_X1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress, 2);
  if (Wire.available() <= 2);
  {
    X0 = Wire.read();
    X1 = Wire.read();
    X1 = X1 << 8; 
    Xg = X0 + X1; 
  }
    if (Xg >= 500 || Xg <= -500) {
      counterx++;
      if (counterx == 1) { 
         MsTimer2::set(500, Clear);
         MsTimer2::start(); 
      }
   }
   if (counterx >= 2) {
    stateX = !stateX;
    return;
  }

  //  Serial.print("X=");
  //  Serial.print(Xg);
  //  Serial.print("  CX=");
  //  Serial.println(counterx);

}

最后我们再回顾一下Lightbox II的前身吧!http://www.i-element.org/%E7%BB%99%E6%88%91%E4%B8%A4%E5%A4%A9%E6%97%B6%E9%97%B4%EF%BC%8C%E8%BF%98%E4%BD%A0%E4%B8%80%E4%B8%AAlightbox/

打赏

Lightbox II 三轴加速度传感器与RGBLED》有5个想法

  1. Hair transfer also known as hair transplantation in turkish name sa ekimi is the operation where the hairs are transplanted to the canals which are opened on the direction of the persons former hair by lateral slits sa ekimi to the requested area. The follicles which are genetically healthy are located in the area between two ears and top side of sa ekimi the nape area are taken one by one with the help of micromotor that is used by Med Hair team.

发表评论

电子邮件地址不会被公开。 必填项已用*标注