В данной статье мы расскажем об опыте сборки куба 4x4x4 на RGB-светодиодах, а также о разработке программного обеспечения, необходимого для использования куба в качестве визуализатора звука. Используется микроконтроллер Arduino Uno.
Подготовка
Куб
При исследовании подобных проектов была обнаружена реализация под названием «Чарликуб» («Charliecube») за авторством Эшера Глика (Asher Glick) и Кевина Бэйкера (Kevin Baker). Данный вариант примечателен тем, что, в отличие от других реализаций, не предусматривает наличие счётчиков, регистров сдвига либо каких-либо других компонентов для построения куба с целью его последующего программирования и задействует только 16 выводов микроконтроллера (позволяя при этом адресовать 64 светодиода). В основе этой реализации лежит конструкция светодиодной индикации под названием «Чарлиплексинг».
Чарлиплексинг
Цифровые выводы микроконтроллеров имеют трёхзначную логику: присоединён к питанию, присоединён к «земле» и не посоединён ни к чему. Если нам надо зажечь светодиод, необходимо подать "+" на X и "-" на «Y», только в таком случае он будет гореть. Если на Y ничего не подавать, до светодиод не загорится. Подробнее о методе можно почитать в одноимённой статье на Википедии, ниже приведено описание работы конкретно в нашем случае.
схема столбика светодиодов
Предположим, что мы хотим зажечь LED1 зелёным цветом. Если проследить по синей линии, видно, что необходимо подать "+" на вход 1. Проследив за красной линией, понимаем, что нужно подать "-" на вход 3. На остальные входы ничего не подаётся.
Визуализация
Было решено, что весь анализ музыки будет производится на подключённом к кубу ПК. Основная идея: ПК анализирует канал записи звука, преобразует звук в информацию о частотах и передаёт данные о ритме музыки в Arduino.Далее микроконтроллер на основе этой информации подсвечивает определённые светодиоды.
Поскольку у авторов проекта большой опыт работы с Ruby, в рамках проекта хотелось прибегнуть именно к этому языку программирования. Была обнаружена статья Дэвида Гутмана (David Guttman), описывающая визуализацию звука на JRuby с помощью гема ruby-processing и java-библиотеки Minim. Найденная статья была взята за основу для написания визуализатора.
Сборка
Собираем столбик
Перед соединением светодиодов в столбец необхобходимо в каждом из четырёх светодиодов выгнуть ноги так, чтобы каждая нога составляла с с соседней 90°.
Затем каждый из светодиодов нужно вращать поочерёдно на 90° (каждый последующий должен быть повёрнут на 90° по часовой стрелке по отношению к предыдущему). Предварительно одну из ног можно пометить (у нас она помечена зелёным лаком), чтобы не запутаться.
Соединяем наши светодиоды в столбик. После соединения светодиодов обрезаем выступающие концы ног.
Размещаем столбики
Оставшиеся 15 столбиков собираются аналогичным образом.
Столбики расставляются на плате на одинаковом расстоянии друг от друга, формируя таким образом куб со стороной, равной 4 светодиодам. Все столбики должны быть повёрнуты в одинаковом направлении (тут очень пригодится предварительная маркировка «опорной» ноги).
Соединяем столбики между собой
Переворачиваем конструкцию и начинаем присоединять провода. Всего проводов 16, соединение проводилось в 4 этапа.
Осталось подключить к Arduino — и можно приступать к программированию.
Подключаем к Arduino
Авторы Чарликуба предусмотрели библиотеку cubeplex для удобного программирования куба с Arduino. Для того, чтобы данную библиотеку можно было использовать без модификаций, необходимо подключать наши провода в следующем порядке (нумерация соответствует проводам на изображениях из предыдущего раздела):
Программируем Arduino
Базовый функционал
Как было сказано выше, авторы воспользовались библиотекой charlieplex, которая предоставляет функцию drawLed(), принимающая цвет и позицию светодиода в координатах XYZ.
#include "cubeplex.h"
const int cubeSides = 4;
void setup() {
initCube();
}
void loop() {
for (int xpos = 0; xpos < cubeSides; xpos++) {
for (int ypos = 0; ypos < cubeSides; ypos++) {
for (int zpos = 0; zpos < cubeSides; zpos++) {
drawLed(red, xpos, ypos, zpos);
}
}
}
}
Обмен сообщениями с ПК
Обмен сообщениями реализуется посредством последовательного ввода-вывода в порт, через который контроллер соединяется с машиной. Работа с такими событиями реализована в Arduino через SerialEvent.
#include "cubeplex.h"
String inputString = "";
boolean stringComplete = false;
// Ввод каждого символа в порт сопровождается вызовом SerialEvent, который накапливает введённые символы в строку inputString.
// Как только пользователь вводит Enter, меняется значение флага inputComplete и выполняется дальнейший код из loop().
int color = red;
void setup() {
Serial.begin(9600);
inputString.reserve(200);
initCube();
}
void loop() {
if (stringComplete) {
Serial.println(inputString);
drawString(inputString);
resetBuffer();
inputString = "";
stringComplete = false;
}
}
}
void serialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read();
inputString += inChar;
if (inChar == 'n') {
stringComplete = true;
}
}
}
// Очистка буфера куба; перед последующей подсветкой диодов куб полностью погаснет.
void resetBuffer() {
flushBuffer();
clearBuffer();
}
// Закодируем три кординаты светодиода трёмя цифрами.
// Каждая координата - каждые три символа из строки, которая пришла в порт.
// То есть строка "000001002003" подсветит столбик с координатами { x: 0, y: 0 }.
void drawString(String inputString) {
int xpos = -1;
int ypos = -1;
int zpos = -1;
for (int i = 0; inputString[i + 3]; i += 3) {
xpos = charToInt(inputString[i]);
ypos = charToInt(inputString[i + 1]);
zpos = charToInt(inputString[i + 2]);
drawLed(color, xpos, ypos, zpos);
}
}
void charToInt(char value) {
return (value - '0');
}
Программирование для светомузыки
Предполагается, что куб будет мигать в такт музыке. Соответственно, можно упростить формат сообщения до одной цифры. Алгоритм такой: как только анализатор музыки «ловит» такт, кубик должен полностью загореться. После этого кубик будет медленно (слой за слоем) гаснуть. Как только анализатор словит следующий такт, кубик снова загнорается полностью. То есть кубику достаточно передать одну цифру: сколько слоёв необходимо подсветить в данный момент. Также при каждой итерации будем случайным образом определять новый цвет.
void drawBeat(String inputString) {
int height = charToInt(inputString[0]);
int color = random(red, white);
for (int xpos = 0; xpos < cubeSides; xpos++) {
for (int ypos = 0; ypos < cubeSides; ypos++) {
for (int zpos = 0; zpos < height; zpos++) {
drawLed(color, xpos, ypos, zpos);
}
}
}
}
Анализ звука на JRuby
В набор библиотеки Minim входит класс BeatDetect, который предоставляет инструменты для определения ритма музыки. Вообще с помощью этой библиотеки предельно просто подключиться к каналу приёма звука и произвести его частотный анализ. Для наших целей подошёл частотный метод определения ритма.
Код тестировался на Ubuntu 15.10; версия JRuby, использованная авторами — jruby 9.0.5.0. Для запуска скрипта необходимо установить Processing и подключить библиотеку Minim.
require 'ruby-processing'
require_relative 'translator'
require_relative 'serial_writer'
class SoundProcessor < Processing::App
load_library "minim"
import "ddf.minim"
import "ddf.minim.analysis"
def setup
@minim = Minim.new self
@input = @minim.get_line_in
@beat = BeatDetect.new @input.mix.size, 44100
@beat_value = 0.001
@beat.set_sensitivity 300
end
def draw
process_beat
SerialWriter.instance.write(Translator.instance.translate(@beat_value))
end
private
def process_beat
@beat.detect @input.mix
@beat_value = @beat.is_kick ? 1 : @beat_value * 0.95
end
end
SoundProcessor.new
Демонстрация работы
Средствами PulseAudio визуализатору в качестве audio input был присвоен audio output, т.е. получаем визуализацию всего звука, который у нас идёт из динамиков. После записи на видео был наложен звук, который воспроизводился в момент создания ролика.
Посесловие
Нам удалось получить визуализатор звука в связке с пк. В дальнейшем можно улучшить алгоритм определения ритма (стандартные средства определения ритма библиотеки Minim далеки от идеала), также на куб можно выводить информацию о частотах. Как видите, куб несложен в построении и программировании; кроме того, он задействует минимум компонентов.
Ссылки:
- Charliecube — Asher Glick
- Чарлиплексинг — Википедия
- Create a Music Visualizer in 7 Steps with Ruby — David Guttman
- Код для Arduino
- Код визуализатора
Авторы
Макоед Виктор и Евгений Куница, студенты 3 курса БГУиР ВМСиС
Автор: vmakoed