电子说
我一直想做一个Arduino项目,但在我的家人被邀请参加之前从未有任何好的想法。花哨的帽子派对。有两个星期的交付时间,我很好奇我是否可以计划和执行动作敏感的LED动画帽。结果我可以!我可能有点过火,但总项目花费大约80美元。通过实验和一些编码,你可以少花钱。
戴着帽子的目标如下:
让一组灯从中心前移动帽子到后面,每侧有一盏灯
改变前后帽子倾斜所决定的灯光行程的速度
帽子乐队允许灯光反转向下倾斜(即模拟重力对灯光的影响)
根据帽子从左向右的倾斜度改变颜色
感觉震动,并显示特殊效果
感觉佩戴者旋转,并显示特殊效果
将其完全包含在帽子中
步骤1:需要的部件
我使用了以下主要组件(包括非联属亚马逊链接):
Teensy LC微控制器 - 由于体积小,我在常规Arduino上选择了它,它有一个特殊的连接来控制我的LED,以及st荣获图书馆和社区支持。
基于Bosch BNO055的位置传感器 - 老实说是我发现的第一个文档之一。有更便宜的选择,但是一旦你弄清楚博世它会为你做很多事情你将不得不做的代码
WS2812可寻址LED灯条 - 我选择1米长的144个LED每米。具有这种密度有助于灯光看起来更像是在移动,而不是按顺序点亮单个元素。
以及以下次要组件:
帽子 - 任何带帽带的帽子都可以。这是来自当地商店的6美元帽子。如果背面有接缝,则更容易接线。注意帽带是否粘在一起,因为这也会造成一些额外的困难。这个是沿着顶部缝制的,但是底部很容易拉起来。
4.7K欧姆电阻器
3x AAA电池盒 - 使用3节AAA电池输出电压,完全符合电子设备所需的范围,简化了操作。 AAA比AA更容易融入帽子,并且仍然具有很好的运行时间。
小规格电线 - 我使用了之前LED项目中的一些实心电线。
烙铁和焊料
一些与帽子内部颜色相匹配的氨纶和线程
建议,但可选:
电池线的快速连接器
帮助工具,这些东西非常小且难以焊接
步骤2:修改帽子
你需要戴帽子的地方安装电子设备和电池的地方。我的妻子专业从事服装工作,所以我向她寻求建议和帮助。我们最终创造了两个氨纶口袋。朝向前部的第一个较小的口袋像帽子本身一样指向,这样当安装电子设备时,位置传感器可以很好地固定到位,但如果需要可以很容易地移除。朝向后面的第二个口袋是将电池组固定到位。
口袋中播放的线条与帽子的颜色相匹配,所有的长度都是冠线。根据帽子和材料的风格,它是由YMMV用这种技术制成的。
我们还发现帽子带在一侧折叠成自己,并且在那个位置完全缝到帽子上。我们不得不移除原始接缝,以便在带下运行LED。在制作期间,它用销钉固定,然后在完成时用匹配的线缝合。
最后,我们打开帽子背面的接缝,如果它被带子覆盖。我们将LED附带的线束穿过该接缝,并将条带中的第一个LED排列在接缝上。然后我们将LED包裹在帽子周围并将条带向下切割,使最后一个LED紧挨着第一个LED。只需使用帽带即可将LED灯条固定到位,但根据您的带和材料,您可能需要通过缝合或粘合来固定LED。
步骤3:连线
Teensy电路板和LED可以在3.3V至5V的任何地方工作。这就是我选择使用3节AAA电池的原因,4.5v的输出电压很好地适用于该范围,并且它们具有足够的运行时间,因为我将LED编程为工作方式。你应该能够超过8小时的运行时间。
接线电源
我将电池盒和LED的正极和负极引线连接在一起,然后焊接到适当位置的Teensy上。电池的正极需要连接到图中Teensy的右上方引脚(在电路板上标记为Vin),负极可以连接到任何标有GND的引脚。方便地,有一个直接位于电路板的另一侧,或紧邻Vin引脚。电路板的完整引脚图可以在本页底部找到。在某些情况下,当您订购电路板时,会包含纸质副本。
如果您计划运行一次只打开几个LED的代码,您可以从Teensy为LED供电本身,通过使用3.3v输出和GND,但是如果你试图拉太多电力,你可能会损坏电路板。因此,为了给自己提供最多选择,最好将LED直接连接到电池电源。
连接LED
我选择了Teensy LC这个项目因为它有一个引脚,可以更容易地连接可寻址的LED。在电路板的底部,左边第二个引脚镜像引脚#17,但也有3.3v。这被称为上拉电阻,而在其他电路板上,您必须连接一个电阻器来提供该电压。对于Teensy LC,您可以直接从该引脚连接到LED数据线。
接线位置传感器
有些BNO055电路板的电压要严格得多,只需3.3v。因此,我在Teensy上的专用3.3v输出端连接了BNO055板上的Vin,这是右侧的第3个引脚。然后,您可以将BNO055上的GND连接到Teensy上的任何GND。
BNO055位置传感器使用I2c与Teensy通信。 I2c需要上拉,所以我将两个4.7K欧姆电阻从Teensy上的3.3v输出连接到引脚18和19.然后将引脚19连接到BNO055板上的SCL引脚,并将18连接到SDA引脚。/p》
接线提示/技巧
为了做这个项目,我使用的是实线而不是搁浅。实心焊丝的一个优点是焊接到这样的原型板上。您可以剥去一些电线,将其弯曲90度,然后将其插入其中一个端子的底部,这样电线的切割端就会粘在电路板上方。然后,您只需要少量焊料将其固定在端子上,您就可以轻松切除多余的焊料。
实心线可能更难以使用,因为它倾向于保持弯曲的方式。然而,对于这个项目来说这是一个优势。我切割和塑造我的电线,使得位置传感器的方向一致,因为我从帽子中插入并移除了电子元件以进行调整和编程。
步骤4:编程
现在所有东西都已组装好,你需要一个Arduino兼容的编程工具。我使用了实际的Arduino IDE(适用于Linux,Mac和PC)。您还需要Teensyduino软件与Teensy板接口。该项目大量使用FastLED库来进行LED的颜色和位置编程。
校准
您要做的第一件事就是去Kris Winer为BNO055提供优秀的GitHub存储库并下载他的BNO_055_Nano_Basic_AHRS_t3.ino草图。在串行监视器运行时安装该代码,它将告诉您BNO055板是否正常联机并通过其自检。它还将引导您校准BNO055,这将在以后为您提供更一致的结果。
花式LED草图入门
专门附加了Fancy LED hat的代码,也附加在我的GitHub存储库中。我计划对代码进行更多调整,这些调整将发布在GitHub repo上。此文件反映了此Instructable发布时的代码。下载并打开草图后,您需要更改一些内容。要更改的大多数重要值都在#define语句的最顶层:
第24行:#define NUM_LEDS 89 - 将其更改为LED条上的实际LED数量
第28行:#define SERIAL_DEBUG false - 您可能希望将此设置为true,以便在串行监视器上看到输出
位置检测代码
位置检测和大部分调整都从742行开始,经过802.我们从位置传感器获取俯仰,滚转和偏航数据并将其用于设定值。根据电子设备的安装方式,您可能需要更改这些设备。如果您将位置传感器的芯片朝向帽子的顶部安装,并且电路板上印有的X旁边的箭头指向帽子的前部,您应该看到以下内容:
Pitch正在点头。
滚动正在倾斜你的头,例如触摸你的耳朵
偏航是哪个方向。你面对的是(北方,西方等)。
如果您的电路板安装在不同的方向,您需要交换俯仰/转动/偏航以使它们按照您的意愿行事。
要调整滚动设置,您可以更改以下#define值:
ROLLOFFSET:在你的帽子稳定并且尽可能居中的情况下,如果Roll不为0,请根据差异进行更改。即如果您在帽子居中时看到在-20处滚动,请将其设为20。
ROLLMAX:用于滚动测量的最大值。戴帽子,右耳向右肩移动,最容易找到。使用串行监视器时,您需要使用长USB电缆。
ROLLMIN:用于滚动测量的最低值,用于向左倾斜时
同样,对于Pitch:
MAXPITCH - 查找时的最大值
MINPITCH - 向下看时的最小值
PITCHCENTER - 直视前的音高值
如果在文件顶部将SERIALDEBUG设置为true,则应该看到Roll/Pitch/Yaw输出的当前值串行监视器,以帮助调整这些值。
您可能想要更改的其他参数
MAX_LED_DELAY 35 - LED粒子可以最慢的移动。这是以毫秒为单位。这是从灯串中的一个LED移动到下一个LED的延迟。
MIN_LED_DELAY 10 - LED颗粒可以移动的禁食。如上所述它是以毫秒为单位。
结论
如果你走得这么远,你应该有一个功能齐全,充满乐趣的, LED帽子!如果你想用它做更多的事情,下一页有一些关于改变设置和做自己的事情的高级信息。以及我的其余代码正在做什么的一些解释。
步骤5:高级和可选:代码内部
影响和自旋检测
影响/自旋检测是使用BNO055的高G传感器功能完成。您可以使用initBNO055()中的以下行来调整它的灵敏度:
第316行:BNO055_ACC_HG_DURATION - 事件必须持续多长时间
第317行: BNO055_ACC_HG_THRESH - 需要有多大的影响
第319行:BNO055_GYR_HR_Z_SET - 转速阈值
第320行:BNO055_GYR_DUR_Z - 转动甚至持续多长时间
两个值均为8位二进制,目前影响设置为B11000000,即255中的192.
当检测到撞击或旋转时,BNO055设置一个值,该值为代码在循环的开头寻找:
// Detect any interrupts triggered, i.e. due to high G
byte intStatus = readByte(BNO055_ADDRESS, BNO055_INT_STATUS);
if(intStatus 》 8) {
impact();
} else if(intStatus 》 0) {
spin();
}
在代码中查找上面的void impact()行以更改影响时的行为,或者使用void spin()来更改旋转行为。
助手
我创建了一个简单的辅助函数(void setAllLeds()),用于快速将所有LED设置为单一颜色。一个用它来关闭它们:
setAllLeds(CRGB::Black);
或者你可以选择FastLED库识别的任何颜色:
setAllLeds(CRGB::Red);
还有一个fadeAllLeds ()函数将所有LED调暗25%。
粒子类
为了大大简化布线,我想使用单个LED串,但让它们表现得像多个字符串。由于这是我的第一次尝试,我希望尽可能简单,所以我将一个字符串视为两个,中间的LED将在那里进行拆分。由于我们可以有偶数或奇数,我们需要考虑到这一点。我从一些全局变量开始:
/*
* Variable and containers for LEDs
*/
CRGB leds[NUM_LEDS];
static unsigned int curLedDelay = MAX_LED_DELAY;
static int centerLed = NUM_LEDS / 2;
static int maxLedPos = NUM_LEDS / 2;
static bool oddLeds = 0;
static bool particleDir = 1;
static bool speedDir = 1;
unsigned long dirCount;
unsigned long hueCount;
以及setup()中的一些代码:
if(NUM_LEDS % 2 == 1) {
oddLeds = 1;
maxLedPos = NUM_LEDS/2;
} else {
oddLeds = 0;
maxLedPos = NUM_LEDS/2 - 1;
}
如果我们有奇数,我们想要使用1/2点作为中间,否则我们想要1/2点-1。这很容易看到10或11个LED:
11个LED:带整数的11/2应该评估因为0到4是一半,6-10是另一半,5是在它们之间。我们在这种情况下将#5视为两者的一部分,即两个虚拟LED串都是#1
10个LED:10/2是5.但是由于计算机从0开始计算,我们需要删除一个。那么我们一半有0 - 4,另一半有5 - 9。第一个虚拟字符串的#1将是4,第二个虚拟字符串的#1将是#5。
然后在我们的粒子代码中,我们必须从我们的整体位置进行一些计数到LED灯串的实际位置:
if(oddLeds) {
Pos1 = centerLed + currPos;
Pos2 = centerLed - currPos;
} else {
Pos1 = centerLed + currPos;
Pos2 = (centerLed -1) - currPos;
}
代码还具有粒子可以改变方向的条件,因此我们还必须考虑到这一点:
if(particleDir) {
if((currPos == NUM_LEDS/2) && oddLeds){
currPos = 0;
} else if((currPos == NUM_LEDS/2 - 1) && (!oddLeds)){
currPos = 0;
} else {
currPos++;
}
} else {
if((currPos == 0) && oddLeds){
currPos = centerLed;
} else if((currPos == 0) && (!oddLeds)){
currPos = centerLed - 1;
} else {
currPos--;
}
}
所以我们使用预期的方向(particleDir ),计算下一个应该点亮的LED,但是我们还必须考虑我们是否已经到达LED灯串的实际端点,或者我们的中心点,它们也作为每个虚拟串的结束。
一旦我们发现了这一切,我们会根据需要点亮下一个灯光:
if(particleDir) {
if(oddLeds) {
Pos1 = centerLed + currPos;
Pos2 = centerLed - currPos;
} else {
Pos1 = centerLed + currPos;
Pos2 = (centerLed -1) - currPos;
}
} else {
if(oddLeds) {
Pos1 = centerLed - currPos;
Pos2 = centerLed + currPos;
} else {
Pos1 = centerLed - currPos;
Pos2 = (centerLed -1) + currPos;
}
}
leds[Pos1] = CHSV(currHue, 255,255);
leds[Pos2] = CHSV(currHue, 255,255);
FastLED.show();
}
为什么要把它作为一个类?实际上,这非常简单,并不需要在课堂上。但是我有未来计划更新代码以允许一次发生多个粒子,并且有些工作正在逆向而其他粒子正在进行中。我认为使用多个粒子进行自旋检测有很多可能性。
全部0条评论
快来发表一下你的评论吧 !