作者:Leonardo
Arduino101火了一段时间了,现在来说101也比刚出来的时候可靠一些了,笔者听同事说用3D打印一个空心的月球,再配合Curie的IMU功能实现灯光的变化,滚动月球就可以实现灯光的炫彩变换,也是挺有意思。




简直就是撩妹神器好吗。。。。
所以下面就从最简单的实现说起,先上代码:
#define ledR 9 //端口宏
#define ledG 6
#define ledB 5
int c1 = 0; //媒介变量
int c2 = 0;
int c3 = 0;
int ledRPWM=0; //脉冲变量
int ledBPWM=0;
int ledGPWM=0;
#include "CurieIMU.h"
void setup()
{
Serial.begin(9600);
while (!Serial);
pinMode(ledR,1); //这三行配置5,6,9号引脚为输出模式
pinMode(ledG,1);
pinMode(ledB,1);
Serial.println("Initializing IMU device...");
CurieIMU.begin();
CurieIMU.setGyroRange(250);
}
void loop()
{
int gxRaw, gyRaw, gzRaw;
float gx, gy, gz;
CurieIMU.readGyro(gxRaw, gyRaw, gzRaw);
gx = convertRawGyro(gxRaw);
gy = convertRawGyro(gyRaw);
gz = convertRawGyro(gzRaw);
c1= abs(gx); //下面这三行吧101获取到的姿态信息做绝对值处理。。
c2= abs(gy);
c3= abs(gz);
if(c18)c1=8;//下面这三行让RGB灯光保持常亮,减少顿挫感。。
if(c28)c2=8;
if(c38)c3=8;
ledRPWM = 255 - c1;//下面这三行取反,因为我的RGB模块是低电平有效
ledGPWM = 255 - c2;
ledBPWM = 255 - c3;
analogWrite(ledR,ledRPWM);//下面这三行实现控制RGB的灯光变换
analogWrite(ledG,ledGPWM);
analogWrite(ledB,ledBPWM);
Serial.print("g:\t");
Serial.print(gx);
Serial.print("\t");
Serial.print(gy);
Serial.print("\t");
Serial.print(c1);//debug用的
Serial.println();
delay(2);
}
float convertRawGyro(int gRaw)
{
float g = (gRaw * 250.0) / 32768.0;
return g;
}

样子就是这么简单,上面的代码就可以实现在arduino滚转的情况下,RGB灯光的变换就实现了,当然,这只是实现,做成月球灯还需要用更多的RGB灯带,同时供电方式也需要考虑。
实现了简单的根据月球的姿态改变颜色的功能,经过思索,如果能添加一个摇动的功能,除在滚动的过程中变换颜色外,在剧烈摇动一下的情况下,就可锁定颜色,岂不是更加方便!最好可以具备以陀螺仪数据(欧拉角)的变化去改变灯光各种颜色的强弱,以及利用加速度数据,实现以加速度强弱来体现颜色强弱,在剧烈摇动后,以加速的方向锁定一个颜色。
好吧,先看代码。。。
#define ledR 9 //端口宏
#define ledG 6
#define ledB 5
// int ca1 = 0; //媒介变量
// int ca2 = 0;
// int ca3 = 0;
int ledRPWM=0; //脉冲变量
int ledBPWM=0;
int ledGPWM=0;
#include "CurieIMU.h"
void setup()
{
Serial.begin(9600);
while (!Serial);
pinMode(ledR,1); //这三行配置5,6,9号引脚为输出模式
pinMode(ledG,1);
pinMode(ledB,1);
Serial.println("Initializing IMU device...");
CurieIMU.begin();
CurieIMU.setGyroRange(255);
Serial.println("Gyro is ready!the range is 255!");
CurieIMU.setAccelerometerRange(2);
Serial.println("Accelerometer is ready!the range is 2!");
CurieIMU.attachInterrupt(eventshock);//开启震动检测中断
Serial.println("shockdetect is ready!");
CurieIMU.setDetectionThreshold(CURIE_IMU_SHOCK, 3000); // 检测加速度大小范围;1.5g = 1500 mg
CurieIMU.setDetectionDuration(CURIE_IMU_SHOCK, 2); // 检测时间;50ms
CurieIMU.interrupts(CURIE_IMU_SHOCK);
Serial.println("IMU initialisation complete, waiting for events...");
}
void loop()
{
int axRaw, ayRaw, azRaw;
float ax, ay, az;
CurieIMU.readAccelerometer(axRaw, ayRaw, azRaw); //获取加速度数据
ax = convertRawAcceleration(axRaw);
ay = convertRawAcceleration(ayRaw);
az = convertRawAcceleration(azRaw);
/////////////////////////
int gxRaw, gyRaw, gzRaw;
float gx, gy, gz;
CurieIMU.readGyro(gxRaw, gyRaw, gzRaw); //获取陀螺仪数据
gx = convertRawGyro(gxRaw);
gy = convertRawGyro(gyRaw);
gz = convertRawGyro(gzRaw);
LEDcontrol_G(gx,gy,gz);
//LEDcontrol_A(ax,ay,az);
// Serial.print("g:\t");
// Serial.print(gx);
// Serial.print("\t");
// Serial.print(gy);
// Serial.print("\t");
// Serial.print(gz);
// Serial.println();
// //////////////
// Serial.print("a:\t");
// Serial.print(ax);
// Serial.print("\t");
// Serial.print(ay);
// Serial.print("\t");
// Serial.print(az);
// Serial.println();
delay(5);
}
void LEDcontrol_G(float cg1,float cg2,float cg3)
{
cg1= abs(cg1); //下面这三行吧101获取到的姿态信息做绝对值处理。。
cg2= abs(cg2);
cg3= abs(cg3);
if(cg18)cg1=8;//下面这三行让RGB灯光保持常亮,减少顿挫感。。
if(cg28)cg2=8;
if(cg38)cg3=8;
ledRPWM = 255 - cg1;//下面这三行取反,因为我的RGB模块是低电平有效
ledGPWM = 255 - cg2;
ledBPWM = 255 - cg3;
analogWrite(ledR,ledRPWM);//下面这三行实现控制RGB的灯光变换
analogWrite(ledG,ledGPWM);
analogWrite(ledB,ledBPWM);
}
void LEDcontrol_A(int ca1,float ca2,float ca3)
{
ca1= abs(ca1)*100; //下面这三行吧101获取到的姿态信息做绝对值处理。。
ca2= abs(ca2)*100;
ca3= abs(ca3)*100;
if(ca18)ca1=8;//下面这三行让RGB灯光保持常亮,减少顿挫感。。
if(ca28)ca2=8;
if(ca38)ca3=8;
ledRPWM = 255 - ca1;//下面这三行取反,因为我的RGB模块是共阳
ledGPWM = 255 - ca2;
ledBPWM = 255 - ca3;
analogWrite(ledR,ledRPWM);//下面这三行实现控制RGB的灯光变换
analogWrite(ledG,ledGPWM);
analogWrite(ledB,ledBPWM);
Serial.println(ledBPWM);
}
void Blue_lightON()
{
analogWrite(ledR,0);
analogWrite(ledG,255);
analogWrite(ledB,255);
delay(3000);
}
void Rad_lightON()
{
analogWrite(ledR,255);
analogWrite(ledG,0);
analogWrite(ledB,255);
delay(3000);
}
void Green_lightON()
{
analogWrite(ledR,255);
analogWrite(ledG,0);
analogWrite(ledB,255);
delay(3000);
}
static void eventshock(void)
{
if (CurieIMU.getInterruptStatus(CURIE_IMU_SHOCK))
{
if (CurieIMU.shockDetected(X_AXIS, POSITIVE))
Blue_lightON();
Serial.println("Negative shock detected on X-axis");
if (CurieIMU.shockDetected(X_AXIS, NEGATIVE))
Blue_lightON();
Serial.println("Positive shock detected on X-axis");
//////////////////////////////////////////////
if (CurieIMU.shockDetected(Y_AXIS, POSITIVE))
Rad_lightON();
Serial.println("Negative shock detected on Y-axis");
if (CurieIMU.shockDetected(Y_AXIS, NEGATIVE))
Rad_lightON();
Serial.println("Positive shock detected on Y-axis");
//////////////////////////////////
if (CurieIMU.shockDetected(Z_AXIS, POSITIVE))
Green_lightON();
Serial.println("Negative shock detected on Z-axis");
if (CurieIMU.shockDetected(Z_AXIS, NEGATIVE))
Green_lightON();
Serial.println("Positive shock detected on Z-axis");
}
}
float convertRawGyro(int gRaw)
{
float g = (gRaw * 250.0) / 32768.0;
return g;
}
float convertRawAcceleration(int aRaw) {
// since we are using 2G range
// -2g maps to a raw value of -32768
// +2g maps to a raw value of 32767
float a = (aRaw * 2.0) / 32768.0;
return a;
}
此上代码可实现刚刚我前面提到的功能,后面,我将会对此代码进行更加深入Curie IMU库的理解。
文章来源:Arduino中文社区