Привет! Каждый уважающий себя DIY-щик, строит графический анализатор спектра. Поделки на радиолампах и диодах уже надоели. Потому сегодня построим полностью механический — из сервоприводов, колб и крутой ферромагнитной жидкости.
Основой программы — быстрое преобразование Фурье. Звук, который слышит человеческое ухо, это колебания с частотой в диапазоне от 20Гц до 20кГц. Звуковые колебания от разных источников — например гитары, барабанов и вокала — сливаются в одну сложную волну. Графический анализатор спектра с помощью преобразования Фурье делит волну на составляющие и показывает набор отдельных частот из которых состоит звук. В этой конструкции каждая пробирка это определённая частота: 63Гц, 160Гц, 400Гц, 1кГц, 2.5кГц, 6.25кГц и 16кГц.
Прошейте плату Iskra Nano Pro кодом программы:
// включаем функцию для логарифмического формата #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); } }
Модель имеет недостатки — кое-где придётся поработать дрелью для того что бы установить электронику или крепления. Но это видно только на стадии сборки, так что будьте внимательны! Архив с чертежами для резки.