您正在使用IE低版浏览器,为了您的雷峰网账号安全和更好的产品体验,强烈建议使用更快更安全的浏览器
此为临时链接,仅用于文章预览,将在时失效
DIY 正文
发私信给吴攀
发送

4

灯光随着音乐动,一起摇摆

本文作者: 吴攀 2015-11-27 17:58
导语:做一个灯光控制器,让它随着音乐动起来!

灯光随着音乐动,一起摇摆

编者注:本文作者为Akiba,原发于FreakLabs

很多人问过我关于灯光控制和排序的问题,其中涉及到安装、显示和可穿戴设计等方方面面,所以我想干脆做一个详细的教程好了!

为此我制作了一个文本教程和一个视频教程,其中视频教程分为两部分,如下所示:

视频一:怎么使用Arduino和Vixen控制发光序列

    时间线:

00:15 - 在面包板上搭建LED电路

01:46 - 配置Vixen软件

03:40 - 设置新的发光顺序

05:12 - 检查音序的串行输出

07:08 - 编写Arduino代码解码音序数据

10:28 - 在Arduino 系统上测试发光序列

视频二:怎么使用无线的方式控制发光序列

    时间线:

00:32 - 将原来的系统改成收发器系统

01:05 - 写出freakduino发送器代码

03:00 - 写入freakduino接收器代码

04:52 - 使用Vixen测试无线系统

05:48 - 使用晶体管实现LED发光条和控制电路的交互

06:55 - 户外测试

07:42 - 实例:花式调酒和Wrecking Crew Orchestra乐队

而视频上看不明白的,就让我们用文字来解决。首先让我们一起来研究一下怎么使用有线的方式实现对LED发光的控制,这样操作起来更加简单,对于新手来说这一步也格外关键。

准备Arduino、面包板和六颗LED灯,按下图的方式进行连接:

灯光随着音乐动,一起摇摆

这里我们选择的是D2~D7这六个输出口连接LED,注意在LED和每个接口之间需要串接一个100Ω的限流电阻。因为LED只需要20mA的电流即可正常发光,串接100Ω的电阻差不多刚好能让标准LED获得良好的表现。按照电路图连接好之后是这样的:

灯光随着音乐动,一起摇摆

首先你可以测试一下LED能不能闪,如果你能控制LED闪烁,你就能控制LED的一切。一旦你学会了控制LED,控制其它电子设备也就是说手到擒来的事情。

Vixen

接下来我们来了解一下Vixen软件,这是一款免费软件。之前我曾经用Vixen 2开发过一个项目,但Vixen 2用起来老是崩溃,还好现在我们有Vixen 3版本了。另外必须注意的一点是Vixen 3支持的系统至少要是Windows 7,并不支持Windows XP。点击这里下载。

Vixen 3的设置比Vixen 2要稍微复杂一点,你必须先摸索一下其将发光方式映射到输出上的方式。(视频上的解释更容易懂一点,但是因为说的是英语,我们还是看看文字版吧。)

灯光随着音乐动,一起摇摆

首先需要配置我们将会用到的发光元素。因为我们只有6个LED,所以我们只需要配置6个单独的元素,其中每个元素都是可调节的灯光或设备,发光等级从0-255可调。

灯光随着音乐动,一起摇摆

另外,你还可以设置调光曲线和显示颜色。调光曲线很容易上手,因为许多LED更多是使用对数调光,而不是线性调光。你可以很轻松地设置设备的线性变化,让它们的发光亮度在0-255之间均匀变化。

灯光随着音乐动,一起摇摆

灯光随着音乐动,一起摇摆

接下来我们需要设置音序器的输出,这里需要用到通用串行端口输出将数据输出到串口,此处需要设置输出的信道的数量。其将会通过串口为每一个信道一次输出一个值。在本项目中,我们需要设置发光单元和信道的一一对应,所以我们需要创建6个信道。

灯光随着音乐动,一起摇摆

灯光随着音乐动,一起摇摆

然后设置串口参数。Vixen 3在这方面比Vixen 2进步不少,因为Vixen 2只能使用计算机的COM1-4,而Vixen 2则能够自动检测计算机的所有串口,并且还都可以使用。串口的设置相对标准,这里采用的参数是57600 bps, 8位, 无奇偶校验和1位停止位。

灯光随着音乐动,一起摇摆

接下来,配置音序器输出发送头文件,该文件是一个ASCII的“+>”,该头文件能够帮助软件实现同步已避免出现掉帧的情况。最坏的情况下,在再次进行同步之前会掉2帧。如果我们设置的时序解析率是10微秒,那么就将出现20微秒的差异,这点时间人类根本无法感知,所以不用担心。

灯光随着音乐动,一起摇摆

最后,我们需要将LED和我们的输出对应起来。因为我们采用的是一一对应的方式,设置方式就很简单了,只需要高亮发光元素和信道,然后点击Patch按钮即可。完成之后,应该就能看到图像化的一一对应示意图了。

灯光随着音乐动,一起摇摆

灯光随着音乐动,一起摇摆

到这里,Vixen的设置就完成了。接下来就该设置新的序列了,点击“Start”按钮开始设置序列流。

灯光随着音乐动,一起摇摆

然后点击New Sequence按钮,会弹出一个用于创建新序列的窗口,可以看到其中每一个LED对应的序列。

灯光随着音乐动,一起摇摆

接下来该在时间上加入音频信号了。

灯光随着音乐动,一起摇摆

下面我用到了一个内置的节奏检测器,可以自动根据音频的节奏在时间线上自动进行标记,这让我们的工作轻松不少。这一步并不是必需的,我们也可以进行手动编辑。

灯光随着音乐动,一起摇摆

灯光随着音乐动,一起摇摆

接下来,还需要为已经标记的重音设置表现效果。因为这些标记都是自动生成的,为他们设置好的表现效果看起来就像是精确控制的实时表现。你可以设置LED在重音点改变颜色、闪烁或者亮度突变。

灯光随着音乐动,一起摇摆

Arduino

接下来是Arduino代码部分。在编程之前,首先需要检查串口出来的数据是什么格式的。不过这一步并不是必须的,只是说能够加深我们对项目的理解,在书写代码时也更加方便。

我利用Arduino的代码实现了一个状态机,通过这个状态机,我们可以很容易地实现串行协议的解码。

#define MAX_CHANNELS 6 

int ch;

int state;

int chVal[MAX_CHANNELS] = {0};

int pins[] = {2, 3, 4, 5, 6, 7};

 

enum states

{

  IDLE,

  DELIM,

  READ,

  DISP

};

 

void setup()

{

  for (ch=0; ch<MAX_CHANNELS; ch++)

  {

    pinMode(pins[ch], OUTPUT);

    digitalWrite(pins[ch], LOW);

  }

  

  state = IDLE;

  ch = 0;

  

  Serial.begin(57600);

}

 

void loop()

{  

  if (Serial.available())

  {

    switch (state)

    {

      case IDLE:  

        ch = 0;

        if (Serial.read() == '+')

        {

          state = DELIM;          

        }

        else

        {

          state = IDLE;

        }

      break;

        

      case DELIM:

        ch = 0;

        if (Serial.read() == '>')

        {

          state = READ;

        }

        else

        {

          state = IDLE;

        }

      break;

      

      case READ:

        chVal[ch++] = Serial.read();

        if (ch >= MAX_CHANNELS)

        {

          ch = 0;

          state = DISP;

        }

      break; 

      

      case DISP:

        state = IDLE;

        for (ch=0; ch<MAX_CHANNELS; ch++)

        {   

          if (chVal[ch] > 0)

          {

            digitalWrite(pins[ch], HIGH);

          }

          else

          {

            digitalWrite(pins[ch], LOW);

          }

        }

      break;

    }

  }

}

这个状态机拥有4个状态,第一个状态为空闲(IDLE)状态,该状态为默认状态。在该状态时,程序等待“+”符号,这是帧标记的起点。“+”进入后,状态机进入第二个状态DELIM。在此状态下,程序等待第二个分隔符标记“>”,此符号到来后则帧开始运作。这样做可以减少出现误报帧的可能,毕竟按一定的序列出现两个特定符号的可能性还是比较小的。

两个符号齐备了之后,状态机进入第三个状态READ,此时读取剩余的帧,并将其存储到数组中。完成之后,状态机过渡到DISP状态。此时我们就要展示我们的数据了。在该状态下,我们会循环数组中的每个数值,如果该数组是非零的,那么就将LED打开,否则就关闭LED。如果我们在这些引脚上再配置上PWM(脉冲宽度调制),就能实现对LED光亮度的控制。但为了教程的简单,这里暂时只使用了简单的开关功能。

上面也就基本上实现了Arduino对LED的控制。接下来我们将换用无线的方式来实现这样的功能。

无线

在开发这个项目时我将Arduino换成了Freakduino,不过本质上都是一样的。

灯光随着音乐动,一起摇摆

这里我使用的是900 MHz大覆盖面积版的Freakduino,这个版本的无线穿墙效果不错,范围也比较大。另外,900MHz频段的干扰也比较少,很少WiFi具有这个频段,在人多的地方进行表演时,这一点格外重要。

#include <chibi.h>

#define MAX_CHANNELS 6

#define MY_ADDR 5

#define DEST_ADDR 3

 

int ch;

int state;

byte chVal[MAX_CHANNELS] = {0};

 

enum states

{

  IDLE,

  DELIM,

  READ,

  DISP

};

 

void setup()

{

  state = IDLE;

  ch = 0;

  

  chibiInit();

  chibiSetShortAddr(MY_ADDR);

  

  Serial.begin(57600);

}

 

void loop()

{  

  if (Serial.available())

  {

    switch (state)

    {

      case IDLE:  

        ch = 0;

        if (Serial.read() == '+')

        {

          state = DELIM;          

        }

        else

        {

          state = IDLE;

        }

      break;

        

      case DELIM:

        ch = 0;

        if (Serial.read() == '>')

        {

          state = READ;

        }

        else

        {

          state = IDLE;

        }

      break;

      

      case READ:

        chVal[ch++] = Serial.read();

        if (ch >= MAX_CHANNELS)

        {

          ch = 0;

          state = DISP;

        }

      break; 

      

      case DISP:

        state = IDLE;

        chibiTx(DEST_ADDR, chVal, MAX_CHANNELS);

      break;

    }

  }

}

首先让我们来看看发送器代码,这个代码和上面有线版本的代码大致类似。其中最主要的不同点是我们需chibiArduino来通过无线的方式来发送代码。chibiArduino是一个无线协议栈,是我根据开放的IEEE 802.15.4标准编写的,我已经在配置和特性上对其进行了很大程度的简化,你只需要简单地启动它就可以实现数据的收发了。不过对一般用户而言,使用什么样的通信标准其实都没有关系。

仔细研究一下代码,你会发现其中还新定义了源地址和目标地址。源地址是我们自己的地址,而目标地址则是数据需要发送到的地址。

我也使用chibiInit()函数初始化了chibiArduino栈,这一步会将栈和寄存器设置成默认值,并使其为数据接收做好准备。chibiSetShortAddr()函数则可以根据我们设置的设备地址和其它设备建立通信。我们只需要设置短地址一次就可以了,然后改地址会被存储到非易失性存储器中。但在这个项目中,我们每一次开机都要对地址进行设置。

我们仍然使用Vixen的状态机来实现对串行协议的解码。在循环代码中,在DISP状态的主要不同在于我们不再循环数据数列和开关LED,我们将数列和通过无线的方式发送给接收器,这一步通过chibiTx()函数实现。chibiTx()含有三个参数:目标地址、以数列形式存储的数据和数据的长度。

#include <chibi.h>

 

#define MAX_CHANNELS 6

#define MY_ADDR 3

#define DEST_ADDR 5

 

int pins[] = {2, 3, 4, 5, 6, 7};

int i;

 

void setup()

{

  for (i=0; i<MAX_CHANNELS; i++)

  {

    pinMode(pins[i], OUTPUT);

    digitalWrite(pins[i], LOW);

  }

  

  chibiInit();

  chibiSetShortAddr(MY_ADDR);

  Serial.begin(57600);

}

 

void loop()

{

  int i;

  

  // Check if any data was received from the radio. If so, then handle it.

  if (chibiDataRcvd() == true)

  { 

    int len, rssi, src_addr;

    byte buf[100];  // this is where we store the received data

    

    // retrieve the data and the signal strength

    len = chibiGetData(buf);

 

    // discard the data if the length is 0. that means its a duplicate packet

    if (len == 0) return;    

 

    rssi = chibiGetRSSI();

    src_addr = chibiGetSrcAddr();

    

    // Print out the message and the signal strength

    Serial.print("Data from node 0x");

    Serial.print(src_addr, HEX);

    Serial.print(": "); 

    for (i=0; i<len; i++)

    {

      if (buf[i] > 0)

      {

        digitalWrite(pins[i], HIGH);

      }

      else

      {

        digitalWrite(pins[i], LOW);

      }

      Serial.print(buf[i]);

      Serial.print(" ");

    }

    Serial.print(", RSSI = 0x"); Serial.println(rssi, HEX);

  }

}

接下来是接收端的代码。在接收端我们需要接受发送端传送的数据,并将这些数据通过LED表现出来。

同样我们首先设置源地址和目标地址,然后我们初始化引脚和chibi栈。

在循环函数中,我们加入了一些新代码。在循环函数中,首先会对数据的接受情况进行检查,如果数据接受,则函数chibiDataRcvd()会返回“真”,然后就接受数据。为了接受数据,我们声明了一个len变量,其存储的是要接收的数据的字节长度以及一个100字节长度的字节数列。为什么要选择100字节呢?因为chibiArduino栈的最大负载为100字节。你可以设置小一点以节约RAM。

然后chibiGetData()函数被作为字节数列的一个参数调用。其将会将接收到的数据逐个写入到这个字节数列中,并返回接收数据的长度。另外,我们进行了一下长度检查,以防止数据长度为0的情况。如果长度为0,则说明我们之前已经接受到过这个数据,这是一个重复的数据包。接收到的数据应该包含6个字节,接下来就是逐个字节检查,并将对应的LED的亮度进行相应的调整。

另外我还在chibiArduino栈中额外增加了一些其它的数据,这些数据不是必需的,但是对调试等工作有很重要的帮助。比如记录信号强度的变化,多个源地址可以从多个来源接收信号,同时也可以对可能的设备故障进行检查,这在户外应用时还是大有裨益的。

至此,对Arduino和Vixen实现对LED灯光的控制的介绍就完成了,赶快自己做一个来装饰你的家吧。

2015-2016赛季全球创客马拉松深圳大学站已经开始接受报名啦!关注“硬创邦”(微信号:leiphone_bang),回复“深大”即可参与报名!此外还可加入全球创客马拉松主群(群号:259592983),参与我们的互动讨论~

灯光随着音乐动,一起摇摆

雷峰网原创文章,未经授权禁止转载。详情见转载须知

分享:
相关文章

编辑

人类尚处于科技文明的黎明时代,如果你已经无法理解现在所发生的一切,请不要惊慌。
当月热门文章
最新文章
请填写申请人资料
姓名
电话
邮箱
微信号
作品链接
个人简介
为了您的账户安全,请验证邮箱
您的邮箱还未验证,完成可获20积分哟!
请验证您的邮箱
立即验证
完善账号信息
您的账号已经绑定,现在您可以设置密码以方便用邮箱登录
立即设置 以后再说