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/

打赏

3 thoughts on “Lightbox II 三轴加速度传感器与RGBLED

Leave a Reply