时隔半年,本学渣终于把lightbox二代憋出来了。
先看看lightbox II是个什么东西吧!
Lightbox II以Arduino Nano为核心,通过三轴加速度传感器ADXL345收集数据,用以选择功能和控制20只共阳级雾状RGBled。不可拆卸,但可以通过无线充电的方式进行充电。
其功能如下:1、在X轴方向摇动 –白光模式
2、在Y轴方向摇动 –自变色
3、在Z轴方向摇动 –随姿态变色

现在进入正题!
工具: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
一、电路连接
总体原理图








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




烧录好程序,测试功能,测试充电效果。做完以上工作之后,这块东西就可以先放在一边了。
二、亚克力和RGBled部分
【点击此处下载lightbox II的CAD图(dwg格式)】如果没有加工设备,可以直接发图给淘宝的店家加工,这里默认亚克力板的厚度为1.7mm。
下载本文的附件,在淘宝搜索“亚克力加工 激光”搜索到相关店家,联系客服,选好合适的亚克力板材(标称2mm,实际1.7mm),名称为《lightbox II(外)》的文件要切双面透明磨砂的亚克力,另外两个文件切不透明的材料,颜色自选,发送dwg文件给客服,确认无误后下单即可。
ATTENTION:
【水深!对于价格一定要货比三家!同时要确认板材实际厚度为1.7mm!】
拿到亚克力后,找到5块有洞的亚克力片,仔细对比尺寸确认他们的位置关系,然后把RGBled装上去。


柔软的维修用飞线是很好的选择,能够适应将亚克力围成长方体的过程。但是要注意,单根线的电流只允许在47mA以下,所以更靠近电源的地方要更多的线来连接,阳极引脚间的飞线也要比阴极引脚的多。焊接的时候要注意确认飞线不容易脱落,以及使用万用表确认是否导通。
没错,这一步非常麻烦。





作者发现502胶水会挥发,在接触面附近再凝结成雾状,有些影响外观。不知道大家有没有好的胶水推荐?

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

大家还可以加上自锁开关和指示灯,加自锁开关记得改CAD图开孔。

四、程序
在这里要先感谢极客工坊的弘毅,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/
可以和我们联系johnson@i-element.org
2015-01-14今天晚上七点,我们在穗石的创托邦咖啡厅有个内部分享会,有兴趣可以过来玩。