Танцующая ферромагнитная жидкость

Привет! Каждый уважающий себя DIY-щик, строит графический анализатор спектра. Поделки на радиолампах и диодах уже надоели. Потому сегодня построим полностью механический — из сервоприводов, колб и крутой ферромагнитной жидкости.

Видеообзор

Что это?

Основой программы — быстрое преобразование Фурье. Звук, который слышит человеческое ухо, это колебания с частотой в диапазоне от 20Гц до 20кГц. Звуковые колебания от разных источников — например гитары, барабанов и вокала — сливаются в одну сложную волну. Графический анализатор спектра с помощью преобразования Фурье делит волну на составляющие и показывает набор отдельных частот из которых состоит звук. В этой конструкции каждая пробирка это определённая частота: 63Гц, 160Гц, 400Гц, 1кГц, 2.5кГц, 6.25кГц и 16кГц.

Что понадобится?

Исходный код

Прошейте плату Iskra Nano Pro кодом программы:

ferrofluid.ino
// включаем функцию для логарифмического формата
#define LOG_OUT           1
// задаем количество выходных отсчетов
#define FFT_N             256
// подключаем библиотеку FFT — быстрое преобразование Фурье
#include <FFT.h>
#include <Servo.h>
// номер пина датчика микрофона
#define MIC_PIN           A0
// частоты с амплитудой меньше не отображаются
#define FREQ_LOW_LEVEL    30
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
Servo servo1;  // 1 серва
Servo servo2;  // 2 серва
Servo servo3;  // 3 серва
Servo servo4;  // 4 серва
Servo servo5;  // 5 серва
Servo servo6;  // 6 серва
Servo servo7;  // 7 серва
 
byte freq_offset[16] = {2, 3, 4, 6, 8, 10, 12, 14};
void setup()
{
  servo1.attach(0);
  servo2.attach(1);
  servo3.attach(2);
  servo4.attach(3);
  servo5.attach(4);
  servo6.attach(5);
  servo7.attach(6);
  sbi(ADCSRA, ADPS2);
  cbi(ADCSRA, ADPS1);
  sbi(ADCSRA, ADPS0);
  analogReference(EXTERNAL);
}
 
void loop()
{
  // считываем заданное количество отсчётов
  for (int i = 0 ; i < FFT_N; i++) {
    // считываем показания
    int sample = analogRead(MIC_PIN);
    // сохраняем действительные значения в четные отсчеты
    fft_input[i] = sample;
  }
  // функция-окно, повышающая частотное разрешение
  fft_window();
  // реорганизовываем данные перед запуском FFT
  fft_reorder();
  // обрабатываем данные в FFT
  fft_run();
  // извлекаем данные, обработанные FFT
  fft_mag_log();
  for (int i = 0; i < 7; i++) {
    int val = map(fft_log_out[freq_offset[i]], FREQ_LOW_LEVEL, 80, 85, 0);
    val = constrain(val, 0, 85);
    if (i == 0 ) servo1.write(val);
    if (i == 1 ) servo2.write(val);
    if (i == 2 ) servo3.write(val);
    if (i == 3 ) servo4.write(val);
    if (i == 4 ) servo5.write(val);
    if (i == 5 ) servo6.write(val);
    if (i == 6 ) servo7.write(val);
  }
}

Корпус и механика

Модель имеет недостатки — кое-где придётся поработать дрелью для того что бы установить электронику или крепления. Но это видно только на стадии сборки, так что будьте внимательны! Архив с чертежами для резки.