Hello there! I am new to microcontrollers, so until this point I got help from friends and chatgpt, but got stucked at some point.
I have here Teensy (i am using Teensy 3.2 controller) code with relay modules and analog microphone sensors in order to detect amplitude from loudspeakers (for each relay and mic there is one speaker). And after detecting the amplitude which is above threshold, it would turn on or off the relay of other speaker.
However, instead of detecting amplitude of the sound, i would like to detect pitch (the speakers are playing human speech sounds). So, i thought of using fft, which whenever there is high pitch detected (above the threshold) it would trigger the relay modules.
A friend suggested this parameter: Goertzel frequency. and here is the example of code i tried. But its not what exactly i want to achieve. It only shows the value where the given Hz is found in a strong or low power.
Question: How can I implement the code i have with relays with pitch detection ?
Here is the code of FFT Goertzel frequency:
/*
Basic frequency detection with Goertzel algorithm
Reads electret mic on A0 and checks for a target frequency
No FFT library, only math functions
*/
#include <Arduino.h>
const int micPin = A0; // microphone analog pin
const float TARGET_FREQ = 2000.0; // frequency to detect (Hz)
const int SAMPLE_RATE = 9000; // Hz, how fast we sample
const int N = 128; // number of samples per block
// Precomputed constants
float coeff;
float Q1, Q2;
void setup() {
Serial.begin(115200);
// precompute coefficient
float omega = (2.0 * PI * TARGET_FREQ) / SAMPLE_RATE;
coeff = 2.0 * cos(omega);
Serial.println("Goertzel frequency detector ready.");
}
void loop() {
float magnitude = detectFrequency();
Serial.print("Magnitude at ");
Serial.print(TARGET_FREQ);
Serial.print(" Hz = ");
Serial.println(magnitude);
delay(100); // small pause
}
// Function to detect target frequency using Goertzel
float detectFrequency() {
Q1 = 0;
Q2 = 0;
for (int i = 0; i < N; i++) {
int sample = analogRead(micPin); // 0–1023
float x = sample - 512; // center to 0
float Q0 = coeff * Q1 - Q2 + x;
Q2 = Q1;
Q1 = Q0;
delayMicroseconds(1000000 / SAMPLE_RATE); // control sampling rate
}
// magnitude calculation
float magnitude = sqrt(Q1 * Q1 + Q2 * Q2 - Q1 * Q2 * coeff);
return magnitude;
}
here is the code with relays:
// Teensy 3.x or 4.x sketch: two‑mic → two‑relay trigger
// ————— Pin assignments —————
const int micA_pin = A0; // Vibration sensor on speaker A
const int micB_pin = A1; // Vibration sensor on speaker B
const int relayA_pin = 6; // Relay for speaker A
const int relayB_pin = 3; // Relay for speaker B
// ————— Trigger parameters —————
const int THRESHOLD = 10; // analogRead() threshold
const unsigned long COOLDOWN = 800; // ms before retrigger
const unsigned long PULSE = 200; // ms relay stays ON
unsigned long lastA = 0, lastB = 0; // last trigger times
unsigned long offTimeA = 0, offTimeB = 0; // times to turn relays OFF
// ————— Serial debug parameters —————
const unsigned long DBG_INTERVAL = 200; // ms between prints
unsigned long lastDbg = 0;
void setup() {
Serial.begin(115200);
while (!Serial);
// inputs
pinMode(micA_pin, INPUT);
pinMode(micB_pin, INPUT);
// outputs (assume active HIGH relay modules)
pinMode(relayA_pin, OUTPUT);
pinMode(relayB_pin, OUTPUT);
digitalWrite(relayA_pin, LOW);
digitalWrite(relayB_pin, LOW);
Serial.println("=== Relay Trigger System ===");
}
void loop() {
unsigned long now = millis();
int lvlA = analogRead(micA_pin);
int lvlB = analogRead(micB_pin);
// 1) periodic debug
if (now - lastDbg >= DBG_INTERVAL) {
Serial.print("Mic A: "); Serial.print(lvlA);
Serial.print(" | Mic B: "); Serial.println(lvlB);
lastDbg = now;
}
if (lvlA > 30)
{
digitalWrite(relayA_pin, LOW);
digitalWrite(relayB_pin, HIGH);
}
if (lvlB > 30)
{
digitalWrite(relayB_pin, LOW);
digitalWrite(relayA_pin, HIGH);
}
delay(100);
// // 2) turn relays off when pulse time expired
// if (offTimeA && now >= offTimeA) {
// digitalWrite(relayA_pin, LOW);
// offTimeA = 0;
// Serial.println("Relay A OFF");
// }
// if (offTimeB && now >= offTimeB) {
// digitalWrite(relayB_pin, LOW);
// offTimeB = 0;
// Serial.println("Relay B OFF");
// }
// // 3) check triggers (with cooldown)
// // Mic A → Relay B
// if (lvlA > THRESHOLD && (now - lastA) >= COOLDOWN) {
// Serial.println(">>> Trigger: Mic A → Relay B ON");
// digitalWrite(relayB_pin, HIGH);
// offTimeB = now + PULSE;
// lastA = now;
// }
// // Mic B → Relay A
// if (lvlB > THRESHOLD && (now - lastB) >= COOLDOWN) {
// Serial.println(">>> Trigger: Mic B → Relay A ON");
// digitalWrite(relayA_pin, HIGH);
// offTimeA = now + PULSE;
// lastB = ;
// }now
// // no delay() — loop runs freely
}
