在本教程中,我们将使用ATMega328P IC制作触摸电容 PCB来控制新像素LED 灯条。我们将在我们的 PCB 上包含一些功能,例如音乐反应模式、随机动画模式和 RGB 控制模式。到目前为止,我们已经制作了触摸电容钢琴,您可以在其中找到 触摸电容的基础知识 技术。现在在本教程中,我们将设计一个基于触控电容的灯板 PCB,它将具有三种不同的模式来控制 Neo-Pixel 条。这些模式是“环形模式”,我们可以使用板上的滑块更改 LED 颜色。第二种模式是“RGB 模式”,我们可以在 RGB 颜色之间更改 LED 灯条的颜色和强度,最后一种模式是“音乐模式”,其中 LED 的颜色和强度会根据音乐播放而变化。这个优雅的项目设计是由 PCBWay制造的 PCB 板实现的,我们还将向您展示该板是如何设计和从 PCBway 订购的
构建前面板 PCB 所需的组件
使用 Arduino Nano 构建 PCB 钢琴需要以下组件。
ATMega328P IC(DIP 封装)
贴片电阻器 (1Mega Ohm, 0805) X 9
贴片电阻 (1K, 0805)x1
压电蜂鸣器
贴片78M05集成电路
贴片电解电容 (10uF,16V,4x45mm) x 2
贴片电容 ( 22pF 0805) x 11
晶体振荡器 (16 MHz)
PCB灯板的电路图
9 个 1Mega Ohm 电阻器连接到 ATMega328P IC 的引脚编号 PB1,作为以下电路图中的公共引脚。数字引脚 PD2 到 PD7 和 PB0 进一步连接到每个电阻的其他连接点。在下图中,剩余的数字引脚连接到 1x5 引脚接头并命名为“剩余数字引脚”。
我们已将八个 22uF 电容器连接到每个电阻器。每个电容器的负极引脚连接到 Atmega328p IC 的接地引脚。然后我们有一个电源部分,为 ATMega328P IC 和 Neo Pixel 提供适当的 5V。
注:如有需要,我们可以加电容。强烈建议使用小电容器 (20pF - 400pF) 来稳定检测到的数据。但是,请确保电容器接地,因为这会降低与体电阻的并联。就我而言,我没有使用电容器,因为没有它们对我来说效果很好。我在上面的示意图中提到了电容器,因此您可以在实际实施过程中轻松添加它们。按照“ CapacitveSensor ”库文档中的规定,以下电容器的值必须介于 20pF 和 400pF 之间。
电容式传感器库如何工作?
这就是 Arduino 库派上用场的地方。感谢“ CapacitiveSensor ”库的作者Paul Bagde r 和Paul Stoffregen 。当我们触摸那个导电板时,我们可以使用这个库来检测电容的变化。在这个库中,其中一个数字引脚用作发送引脚(作为 OUTPUT),而另一个用作接收引脚(作为 INPUT)。发送引脚变为高电平和接收引脚变为高电平之间的持续时间是检测电容变化的唯一方法。当您将发送引脚设置为高电平(或5 伏)时,电阻-电容对会在发送引脚变为高电平之间产生延迟 当接收引脚从发送引脚读取高值时。CapacitiveSensor 库提供了一个将发送引脚设置为高电平的函数,然后等待并计数,直到接收引脚被读取为高电平。此函数返回可用于检测电容变化的时间值。当时间值增大或减小时,表明电容值发生了变化。当电容较大时,接收引脚将需要更长的时间才能达到高电平,而当电容较小时,将需要更短的时间才能达到高电平。因此,我们可以确定正常状态是什么,然后在每次发送引脚切换时检查更改。
为PCB灯板制造PCB
现在我们有了原理图,我们可以继续为基于触摸电容的 PCB 灯板布置 PCB。您可以使用您选择的任何 PCB 软件来设计 PCB。在这里,我们使用 EasyEDA 平台为我们的项目创建原理图和 PCB。下面是PCB Light Panel顶层和底层的3D模型视图:
上述电路的 PCB 布局也可以从下面给出的链接下载为 Gerber:
项目的 Gerber 文件
组装触控电容灯面板 PCB
订购板后,几天后,它通过快递在一个标签整齐且包装完好的盒子中到达我的手中。PCB质量一如既往的好。板子的顶层和底层如下图所示:
在确保轨道和脚印是正确的之后。我继续组装PCB。完全焊接的板如下所示:
PCB灯板编程
触摸电容式 PCB 灯板的完整代码可以从该项目的 github 存储库中下载。“ CapacitiveSensor ”库非常易于使用,并且他们提供了有关如何使用该库的很好的文档。在进入程序之前,让我们在 Arduino IDE 上安装“ CapacitiveSensor”库。您需要下载库的 zip 文件。然后转到Arduino IDE 工具栏下的“ Sketch -> Include Library ”部分。使用“添加 .Zip 库...”选项添加 zip 文件,如下图所示。然后重新启动 Arduino IDE。类似的方式你也可以安装ADCTouch.h库。
现在安装所需的库文件后,通过包含所有库文件来启动代码。Adafruit_NeoPixel.h 用于控制基于单线的 LED 像素和灯条。在这里,我们使用它来控制 Neo-Pixel LED 灯条。CapacitiveSensor 库用于感应 PCB 焊盘上的触摸。
#include#include <电容传感器.h> #include
然后在接下来的几行中,我们使用CapacitiveSensor()函数创建了九个实例。这些实例定义了连接触摸板的引脚。此函数的语法是CapacitiveSensor(byte sendPin, byte receivePin),其中一个数字引脚用作发送引脚(作为 OUTPUT),而另一个用作此库中的接收引脚(作为 INPUT)。
CapacitiveSensor Mode_Pad = CapacitiveSensor(9,8); CapacitiveSensor RGB_Pad = CapacitiveSensor(9,7); CapacitiveSensor Music_Pad = CapacitiveSensor(9,6); 电容传感器 Ring_L_Pad = 电容传感器(9,5); 电容传感器 Ring_LT_Pad = 电容传感器(9,4); 电容传感器 Ring_T_Pad = 电容传感器(9,3); 电容传感器 Ring_TR_Pad = 电容传感器(9,2);
之后,声明 Neo Pixel 条对象,其中 Argument 1 是 Neo Pixel 条中的像素数,Argument 2 是连接 LED 条的引脚。
Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_PIXELS, PIN, NEO_GRB + NEO_KHZ800);
然后我们定义了一些函数来检测垫和环上的触摸。前三个函数ModeMode()、RGBMode()和MusicMode()用于检测用于在 PCB 不同模式之间切换的焊盘上的触摸。在第一个函数中,我们将读取第一个焊盘的值,即“MODE”,如果检测到的值大于 500,则它将返回 1,否则返回 0。同样,我们为 RGB pad 和 MUSIC pad 定义了另外两个函数。
布尔模式模式(){ long Mode_Pad_Value = Mode_Pad.capacitiveSensor(30; 如果 (Mode_Pad_Value>500) 返回 1; 别的 返回0; } 布尔 RGBMode(){ 长 RGB_Pad_Value = RGB_Pad.capacitiveSensor(30); 如果(RGB_Pad_Value>500) 返回 1; 别的 返回0; } 布尔音乐模式(){ 长 Music_Pad_Value = Music_Pad.capacitiveSensor(30); 如果(Music_Pad_Value>500) 返回 1; 别的 返回0; }
Check_Ring_Pos()函数用于检测环上的触摸。除此之外,它还存储环位置。这些环位置用于检测环上的顺时针或逆时针旋转。同样,我们定义了另一个函数来检查滑块位置,并且我们还使用滑块上的焊盘位置检查滑动方向。
字符 Check_Ring_Pos() { char ring_pos = 0; 字符结果 = 0; 长 Ring_L_Pad_Value = Ring_L_Pad.capacitiveSensor(30); 长 Ring_LT_Pad_Value = Ring_LT_Pad.capacitiveSensor(30); 长 Ring_T_Pad_Value = Ring_T_Pad.capacitiveSensor(30); 长 Ring_TR_Pad_Value = Ring_TR_Pad.capacitiveSensor(30); 如果(Ring_L_Pad_Value>500) ring_pos = 1; 如果(Ring_LT_Pad_Value>500) ring_pos = 2; 如果(Ring_T_Pad_Value>500) ring_pos = 3; 如果(Ring_TR_Pad_Value>500) ring_pos = 4; char current_ring_pos = ring_pos; Serial.println(current_ring_pos - pvs_ring_pos); 如果 ((current_ring_pos - pvs_ring_pos) == 1) 结果 = 1; 如果 ((current_ring_pos - pvs_ring_pos) == -1) 结果=2; if (current_ring_pos != pvs_ring_pos); pvs_ring_pos = current_ring_pos; 返回结果; }
现在我们知道是否触摸了特定的垫子,如果是,那么在哪个方向上,我们将使用这些读数在三种模式之间切换。在RGB 模式下,我们可以使用滑块来增加或减少灯光的强度。如果我们从左向右滑动,强度会增加,如果我们从右向左滑动,强度会降低。同样,我们可以使用顺时针或逆时针方向的环形垫来改变颜色。在模式模式下,环形垫 将用于顺时针和逆时针方向旋转灯。
无效 RGB_Mode(){ Serial.print("我们已进入 RGB 模式"); 嘟(); uint16_t i, j, k; 亮度 = 255; 而(1){ char Sider_Status = Check_Slider_Pos(); char Ring_Status = Check_Ring_Pos(); if (Sider_Status ==1){ // 不移动返回 0,从右到左返回 2 Serial.println("从左向右移动"); 嘟(); 亮度=亮度+50; Serial.print(亮度); } …………………………………………..
现在,如果触摸音乐模式键盘,Arduino 将开始读取麦克风读数,并根据音乐随机改变灯光的强度和颜色。
无效音乐模式(){ Serial.print("我们已经进入音乐模式"); 嘟(); 而(1){ 如果(数字读取(A5)==低) { Serial.print("TAP"); for(int i=0; i< 48; i++) { strip.setBrightness(随机(100,255)); strip.setPixelColor(i, strip.Color(随机 (0,255), 随机 (0,255), 随机 (0,255))); 剥离.show(); }
3D打印触控电容式PCB灯板外壳
现在的想法是将这个 PCB 灯板挂在墙上,为此,我打印了一个 PCB 支架。我用我的游标测量了装置的尺寸来设计一个外壳。完成后,我的设计如下所示。STL 文件也可以从Thingiverse下载,您可以使用它打印您的外壳。
测试触控电容式 PCB 灯板
组装好 PCB 并对 ATMega328 进行编程后,我们现在可以测试设置了。为此,将 3D 打印支架安装在 PCB 上并包裹 Neo-pixel 条,如下所示:
现在使用 12V 适配器为电路板供电。您可以使用 MODE、RGB 和 MUSIC 三个触摸板在不同模式之间切换,并使用滑块来更改灯光的强度和颜色。
代码
#include 《Adafruit_NeoPixel.h》
#include 《CapacitiveSensor.h》
#include 《ADCTouch.h》
#define PIN 10 //Neo 像素连接到引脚 10
#define BUZZER 13 //BUZZER 连接到引脚 D13
#define N_PIXELS 23 / /48 neopixel in led strip
#define MIC A5 // 麦克风连接在引脚 A5
#define N 10 // 样本数
#define fadeDelay 25 // 淡入淡出量
#define noiseLevel 25 // 我们想要切断的噪音量
int参考 1,参考 2,参考 3,参考 4,参考 5;//使用模拟引脚消除偏移的参考值是电容触摸
char pvs_slider_pos = 0;
字符 pvs_ring_pos = 0;
整数样本[N];// 存储样本
int periodFactor = 0; // 用于周期计算
诠释 t1 = -1;
诠释T;
坡度;
字节 periodChanged = 0;
诠释亮度=0;
int led_position=0;
CapacitiveSensor Mode_Pad = CapacitiveSensor(9,8);
CapacitiveSensor RGB_Pad = CapacitiveSensor(9,7);
CapacitiveSensor Music_Pad = CapacitiveSensor(9,6);
电容传感器 Ring_L_Pad = 电容传感器(9,5);
电容传感器 Ring_LT_Pad = 电容传感器(9,4);
电容传感器 Ring_T_Pad = 电容传感器(9,3);
电容传感器 Ring_TR_Pad = 电容传感器(9,2);
//创建一个 NeoPixel 条带
Adafruit_NeoPixel strip = Adafruit_NeoPixel(N_PIXELS, PIN, NEO_GRB + NEO_KHZ800);
布尔模式模式(){
long Mode_Pad_Value = Mode_Pad.capacitiveSensor(30);
如果 (Mode_Pad_Value》500)
返回 1;
否则
返回 0;
}
boolean RGBMode(){
long RGB_Pad_Value = RGB_Pad.capacitiveSensor(30);
如果 (RGB_Pad_Value》500)
返回 1;
否则
返回 0;
}
boolean MusicMode(){
long Music_Pad_Value = Music_Pad.capacitiveSensor(30);
如果 (Music_Pad_Value》500)
返回 1;
否则
返回 0;
}
char Check_Ring_Pos()
{
char ring_pos = 0;
字符结果 = 0;
长 Ring_L_Pad_Value = Ring_L_Pad.capacitiveSensor(30);
长 Ring_LT_Pad_Value = Ring_LT_Pad.capacitiveSensor(30);
长 Ring_T_Pad_Value = Ring_T_Pad.capacitiveSensor(30);
长 Ring_TR_Pad_Value = Ring_TR_Pad.capacitiveSensor(30);
如果 (Ring_L_Pad_Value》500)
ring_pos = 1;
如果 (Ring_LT_Pad_Value》500)
ring_pos = 2;
如果 (Ring_T_Pad_Value》500)
ring_pos = 3;
如果 (Ring_TR_Pad_Value》500)
ring_pos = 4;
char current_ring_pos = ring_pos;
Serial.println(current_ring_pos - pvs_ring_pos);
if ((current_ring_pos - pvs_ring_pos) == 1)
结果 = 1; //Serial.print(“顺时针触摸环”);
如果 ((current_ring_pos - pvs_ring_pos) == -1)
结果 =2; //Serial.print(“环逆时针触摸”);
if (current_ring_pos != pvs_ring_pos);
pvs_ring_pos = current_ring_pos;
返回结果;
}
char Check_Slider_Pos()
{
char slider_pos = 0;
字符结果 = 0;
int sensorValue1 = ADCTouch.read(A0);
int sensorValue2 = ADCTouch.read(A1);
int sensorValue3 = ADCTouch.read(A2);
int sensorValue4 = ADCTouch.read(A3);
int sensorValue5 = ADCTouch.read(A4);
传感器值1-= ref1;
传感器值2-= ref2;
传感器值3-= ref3;
传感器值4-= ref4;
传感器值5-= ref5;
如果(sensorValue1》50)
slider_pos = ‘1’;
如果(sensorValue2》50)
slider_pos = ‘2’;
if (sensorValue3》50)
slider_pos = ‘3’;
如果(sensorValue4》50)
slider_pos = ‘4’;
如果(sensorValue5》50)
slider_pos = ‘5’;
char current_slider_pos = slider_pos;
if ((current_slider_pos - pvs_slider_pos) == 1)
结果 = 1; //Serial.print(“滑块从左到右”);
if ((current_slider_pos - pvs_slider_pos) == -1)
结果 =2; //Serial.print(“滑块从右到左”);
if (current_slider_pos != pvs_slider_pos);
pvs_slider_pos = current_slider_pos;
返回结果;
}
void RGB_Mode(){
Serial.print(“我们已进入 RGB 模式”);
嘟();
uint16_t i, j, k;
亮度 = 255;
while(1){ //保持 RGB 模式
char Sider_Status = Check_Slider_Pos();
char Ring_Status = Check_Ring_Pos();
if (Sider_Status ==1){ // 不移动返回 0,从右到左返回 2
Serial.println (“Moved Left to Right”);
嘟();
亮度=亮度+50;
Serial.print(亮度);
}
if (Sider_Status==2){ // 不移动返回 0,从右到左返回 2
Serial.println (“Moved Right to Left”);
嘟();
亮度 = 亮度-50;
Serial.print(亮度);
}
if (Ring_Status==1) {//返回 0 表示不移动,2 表示逆时针
Serial.println (“Ring in Clockwise”);
嘟();
i = 随机(0,255);
j = 随机 (0,255);
k=随机(0,255);
}
if (Ring_Status==2) {//返回 0 表示不移动,返回 2 表示逆时针
Serial.println (“Ring in Counter-Clockwise”);
嘟();
i = 随机(0,255);
j = 随机 (0,255);
k=随机(0,255);
}
for(int x=0; x《N_PIXELS; x++) {
strip.setBrightness(Brightness);
strip.setPixelColor(x, strip.Color(i,j,k));
剥离.show();
}
if ( RGBMode() || ModeMode() || MusicMode())
中断;
}
}
void Mode_Mode(){
Serial.print(“我们已进入 MODE 模式”);
嘟();
while(1){ //保持 RGB 模式
char Ring_Status = Check_Ring_Pos();
if (Ring_Status==1) {//返回 0 表示不移动,2 表示逆时针
Serial.println (“Ring in Clockwise”);
嘟();
}
for(int i=0; i《 48; i++) {
strip.setBrightness(255);
strip.fill(255,(i+0),(1+i));
strip.fill(0,0,i);
剥离.show();
延迟(20);
}
if (Ring_Status==2){ // 不移动返回 0,逆时针返回 2
Serial.println (“Ring in Anti- Clockwise”);
嘟();
for(int i=48; i》0; i--) {
strip.setBrightness(255);
strip.fill(255,(i+0),(1+i));
strip.fill(0,0,i);
剥离.show();
延迟(20);
}
}
if ( RGBMode() || ModeMode() || MusicMode())
中断;
}
}
void Music_Mode(){
Serial.print(“我们已进入音乐模式”);
嘟();
while(1){ //保持 RGB 模式
if (digitalRead(A5)==LOW)
{
Serial.print(“TAP”);
for(int i=0; i《 48; i++)
{
strip.setBrightness(随机(100,255));
strip.setPixelColor(i, strip.Color(随机 (0,255), 随机 (0,255), 随机 (0,255)));
剥离.show();
}
延迟(100);
}
else
{
for(int i=0; i《 48; i++)
{
strip.setBrightness(0);
strip.setPixelColor(i, strip.Color(随机 (0,255), 随机 (0,255), 随机 (0,255)));
剥离.show();
}
}
if ( RGBMode() || ModeMode() || MusicMode() )
中断;
}
}
void setup() {
// 启动条带并将其
清空 strip.begin();
//strip.show();
//cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF); // 关闭通道 1 上的自动校准 - 仅作为示例
Serial.begin(9600);
ref1 = ADCTouch.read(A0, 500);
ref2 = ADCTouch.read(A1, 500);
ref3 = ADCTouch.read(A2, 500);
ref4 = ADCTouch.read(A3, 500);
ref5 = ADCTouch.read(A4, 500);
pinMode(蜂鸣器,输出);
}
void loop() {
//strip.clear();
剥离.show();
if (ModeMode()==1)
Mode_Mode();
if (RGBMode()==1)
RGB_Mode();
if (MusicMode()==1)
Music_Mode();
}
无效哔(){
音(蜂鸣器,400);
延迟(50);
无音(蜂鸣器);
}
全部0条评论
快来发表一下你的评论吧 !