Heinrich
Member
Hi,
I am a beginner.
After thoroughly reading relevant threads in this forum I still have a lot of questions regarding a project I am doing right now (part of a MA thesis in Design)
I am trying to get following setup to work and have a couple of issues/questions i ran into using the Teensy Audio Library:
Hardware:
Teensy 3.5
MAX4466 Microphone
LiquidCystal Display (as a substitute before using steppermotors with TMC2100 SilentStepStick, and Nema17)
Potentiometer
Description:
I would like to separate frequencies of different surroundings and use the values of the FFT after conversion into dB values to control (for now) one Steppermotor. My thought is to use a potentiometer to scroll through the FFT bands and select a desired one to see whats is going on there. I started with the SpectrumAnalyzerBasic from the Audio library and made some changes since I don't own an AudioShield (yet )
Issues:
0. Is it possible in general to drive a stepper motor and run FFT together from one Teensy? If so, does it need to be sequentially or can i do the fft while the stepper is running (Accelstepper and TeensyStep seem to support imediate return)
1. I don't quite understand how to translate the raw FFT values into db. This thread seems to have a solution:
but to me as a novice it is not clear which values are n,r and f.
2. When adding the potentiometer
the Arduino IDE compiles and uploads it but nothing is printed to the Serial monitor and it seems the microphone and the display stop picking up and displaying the sound. It somehow works if putting this snippet at the end of the loop but then the mapping function wont work, I even got very high values (around 65000) when turning the Pot. I have tested the same setup in a separate sketch where it functioned flawlessly.
3. If it is possible to get the Pot to work together with the rest of the code, is there a more elegant solution than this to select the desired band from the array "levels":
4. I got the original code to work with the MAX4466 (following this guideline). The pot is turned all way ccw but even then the general sound level has to be very high for the mic to pic up anything. This
seems to influence it a bit but eventually (with higher numbers) the first two bands will raise much more whilst being inert. Is there a better Mic you could recommend? (The teensy audio shield is ordered)
I'm aware there are a lot of open questions in this project but I thought I'll give it a try here anyway...any help/criticism/feedback and support is highly appreciated!
Cheers /h
here is the full code for now:
I am a beginner.
After thoroughly reading relevant threads in this forum I still have a lot of questions regarding a project I am doing right now (part of a MA thesis in Design)
I am trying to get following setup to work and have a couple of issues/questions i ran into using the Teensy Audio Library:
Hardware:
Teensy 3.5
MAX4466 Microphone
LiquidCystal Display (as a substitute before using steppermotors with TMC2100 SilentStepStick, and Nema17)
Potentiometer
Description:
I would like to separate frequencies of different surroundings and use the values of the FFT after conversion into dB values to control (for now) one Steppermotor. My thought is to use a potentiometer to scroll through the FFT bands and select a desired one to see whats is going on there. I started with the SpectrumAnalyzerBasic from the Audio library and made some changes since I don't own an AudioShield (yet )
Issues:
0. Is it possible in general to drive a stepper motor and run FFT together from one Teensy? If so, does it need to be sequentially or can i do the fft while the stepper is running (Accelstepper and TeensyStep seem to support imediate return)
1. I don't quite understand how to translate the raw FFT values into db. This thread seems to have a solution:
Code:
float db(float n, float r) {
if (n <= 0) return r-96; // or whatever you consider to be "off"
return r+log10f(n) * 20.0f;
}
2. When adding the potentiometer
Code:
sel = map(analogRead(14), 0, 1023, 0, 15);
Serial.println(sel);
3. If it is possible to get the Pot to work together with the rest of the code, is there a more elegant solution than this to select the desired band from the array "levels":
Code:
if (sel == 0) {
serial.print(level[0], 3);
};
else if (sel == 1) {
serial.print(level[1], 3);
};
else if (sel == 2) {
serial.print(level[2], 3);
};
else if (sel == 3) {
serial.print(level[3], 3);
};
...
4. I got the original code to work with the MAX4466 (following this guideline). The pot is turned all way ccw but even then the general sound level has to be very high for the mic to pic up anything. This
Code:
// configure the mixer to equally add left & right
mixer1.gain(0, 10);
I'm aware there are a lot of open questions in this project but I thought I'll give it a try here anyway...any help/criticism/feedback and support is highly appreciated!
Cheers /h
here is the full code for now:
Code:
#include <LiquidCrystal.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// GUItool: begin automatically generated code
AudioInputAnalog adc1; //xy=349.0000114440918,284.00000858306885
AudioMixer4 mixer1; //xy=504.0000114440918,303.0000114440918
AudioAnalyzeFFT1024 fft1024; //xy=659.0000228881836,302.0000319480896
AudioConnection patchCord1(adc1, 0, mixer1, 0);
AudioConnection patchCord2(mixer1, fft1024);
// GUItool: end automatically generated code
// The scale sets how much sound is needed in each frequency range to
// show all 8 bars. Higher numbers are more sensitive.
float scale = 40.0;
// An array to hold the 16 frequency bands
float level[16];
//float level[8];
//float level[5];
// This array holds the on-screen levels. When the signal drops quickly,
// these are used to lower the on-screen level 1 bar per update, which
// looks more pleasing to corresponds to human sound perception.
int shown[16];
//int shown[8];
//int shown[5];
int sel; //to choose the displayed band
// Use the LiquidCrystal library to display the spectrum
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
byte bar1[8] = {0, 0, 0, 0, 0, 0, 0, 255};
byte bar2[8] = {0, 0, 0, 0, 0, 0, 255, 255}; // 8 bar graph
byte bar3[8] = {0, 0, 0, 0, 0, 255, 255, 255}; // custom
byte bar4[8] = {0, 0, 0, 0, 255, 255, 255, 255}; // characters
byte bar5[8] = {0, 0, 0, 255, 255, 255, 255, 255};
byte bar6[8] = {0, 0, 255, 255, 255, 255, 255, 255};
byte bar7[8] = {0, 255, 255, 255, 255, 255, 255, 255};
byte bar8[8] = {255, 255, 255, 255, 255, 255, 255, 255};
void setup() {
// Audio requires memory to work.
AudioMemory(12);
//fft1024.windowFunction(AudioWindowHanning1024);
//fft1024.windowFunction(AudioWindowFlattop1024);
//turn on the LCD and define the custom characters
lcd.begin(16, 2);
lcd.print("freqSpec");
lcd.createChar(0, bar1);
lcd.createChar(1, bar2);
lcd.createChar(2, bar3);
lcd.createChar(3, bar4);
lcd.createChar(4, bar5);
lcd.createChar(5, bar6);
lcd.createChar(6, bar7);
lcd.createChar(7, bar8);
// configure the mixer to equally add left & right
mixer1.gain(0, 10);
// pin 21 will select rapid vs animated display
//pinMode(21, INPUT_PULLUP);
}
void loop() {
sel = map(analogRead(14), 0, 1023, 0, 15);
Serial.println(sel);
if (fft1024.available()) {
level[0] = fft1024.read(0);
level[1] = fft1024.read(1);
level[2] = fft1024.read(2, 3);
level[3] = fft1024.read(4, 6);
level[4] = fft1024.read(7, 10);
level[5] = fft1024.read(11, 15);
level[6] = fft1024.read(16, 22);
level[7] = fft1024.read(23, 32);
level[8] = fft1024.read(33, 46);
level[9] = fft1024.read(47, 66);
level[10] = fft1024.read(67, 93);
level[11] = fft1024.read(94, 131);
level[12] = fft1024.read(132, 184);
level[13] = fft1024.read(185, 257);
level[14] = fft1024.read(258, 359);
level[15] = fft1024.read(360, 511);
/*
level[0] = fft1024.read(0);
level[1] = fft1024.read(1, 4);
level[2] = fft1024.read(5, 24);
level[3] = fft1024.read(25, 113);
level[4] = fft1024.read(114, 511);
*/
/*
level[0] = fft1024.read(0);
level[1] = fft1024.read(1, 2);
level[2] = fft1024.read(3, 7);
level[3] = fft1024.read(8, 18);
level[4] = fft1024.read(19, 43);
level[5] = fft1024.read(44, 100);
level[6] = fft1024.read(101, 227);
level[7] = fft1024.read(228, 511);
*/
// begin drawing at the first character on the 2nd row
lcd.setCursor(0, 1);
for (int i = 0; i < 16; i++) {
Serial.print(level[i], 3);
// conversion from FFT data to display bars should be
// exponentially scaled. HOW?
int val = level[i] * scale;
if (val > 8) val = 8;
if (val >= shown[i]) {
shown[i] = val;
} else {
if (shown[i] > 0) shown[i] = shown[i] - 1;
val = shown[i];
}
//Serial.print(shown[i]);
Serial.print(" ");
// print each custom digit
if (shown[i] == 0) {
lcd.write(' ');
} else {
lcd.write(shown[i] - 1);
}
}
Serial.print(" cpu:");
Serial.println(AudioProcessorUsageMax());
//delay(100);
}
}
Code:
Last edited: