Arduino Uno Translate FFT Audio into Vibration Motors

Hey there,

for a uni project I'm trying to translate frequencies into 4 different vibration motors
I ordered a MSGEQ7 but they are very hard to come by and the order process is taking very long, hence i tried the FFT route instead.
I first tried the FFT translation with LEDs as outputs for different frequency ranges, as it should be simpler and give a visual feedback.
I asked a friend for help and he coded something that works. However it does not output to the LEDs in question, but according to the monitor it does pick up frequencies correctly. Does anyone know what could be wrong? And how could I use this FFT reading to trigger vibration motors as opposed to LED pins on the board?

Thanks a ton!

#include "fix_fft.h"
#define SAMPLES 128 //define according to your need
#define AUDIO A0
#define ledLowsGreen A1
#define ledLowMidsYellow A2
#define ledMidsBlue A3
#define ledHighMidsWhite A4
#define ledHighsRed A5

// array of leds to switch the values
int ledarray[5] = { A1, A2, A3, A4, A5 };
// value to compile the data into 128 / dividor
int dividor = 21;
char im[SAMPLES];
char data[SAMPLES];
int barht[SAMPLES];

void setup()
{
  Serial.begin(9600);
  pinMode(ledLowsGreen, OUTPUT);
  pinMode(ledLowMidsYellow, OUTPUT);
  pinMode(ledMidsBlue, OUTPUT);
  pinMode(ledHighMidsWhite, OUTPUT);
  pinMode(ledHighsRed , OUTPUT);
}

void loop()
{
  static int i, j;
  int val;
  // get audio data
  for (i = 0; i < SAMPLES; i++)
  {
    val = analogRead(AUDIO); // 0-1023
    data[i] = (char)(val / 4 - SAMPLES); // store as char
    im[i] = 0; // init all as 0
  }
  // run FFT
  fix_fft(data, im, 7, 0);
  // extract absolute value of data only, for 32 results
  for (i = 0; i < SAMPLES; i++)
  {
    barht[i] = (int)sqrt(data[i] * data[i] + im[i] * im[i]);
  }

  for (i = 0, j = 0; i < SAMPLES / dividor; i++, j += dividor)
  {
    for (int x = 0 ; x < dividor; x++)
    {
      barht[i] = barht[i] + (barht[j + x]);
    }
  }

// display 5 leds
for (int k = 1; k < SAMPLES / dividor; k++) {
      analogWrite(ledarray[5],barht[k]);
     }


  // display Serial plotter
  for (int k = 1; k < SAMPLES / dividor; k++) {
    Serial.print("Band_");
    Serial.print(k);
    Serial.print(":");
    if ( k + 1 == (SAMPLES / dividor))
    {
      Serial.println();
      break;
    }
    else
    {
      Serial.print(", ");
    }
  }

  for (int k = 1; k < SAMPLES / dividor; k++) {
    Serial.print(barht[k]);
    //analogWrite(ledarray[5],barht[k])
    if ( k + 1 == (SAMPLES / dividor))
    {
      Serial.println();
      break;
    }
    else
    {
      Serial.print(", ");
    }
  }
}

Here, you are attempting to write an analog value to a pin identified by ledarray[5], which does not exist.

analogWrite(ledarray[5],barht[k]);

To control LED brightness, you need to use digital pins capable of being controlled by analogWrite() function, i.e. PWM pins.

You need to verify that the values of barht[k] are between 0 and 255, as well.

Can you tell us what this code is supposed to do?

  for (i = 0, j = 0; i < SAMPLES / dividor; i++, j += dividor)
  {
    for (int x = 0 ; x < dividor; x++)
    {
      barht[i] = barht[i] + (barht[j + x]);
    }
  }

analogWrite is nothing to do with analog input pins, its PWM output. (a common trap for the unwary).

The duty cycle is controlled by analogWrite on PWM pins. On non-PWM pins it outputs HIGH if the value is 128 or greater and LOW if the value is 127 or less.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.