How to get values from a speaker ?

Hello,
I'm building a bluetooth speaker with an arduino and a bluetooth Amp,
I'm able to play music, but I have issues to understand how to get any value from the speaker to make an LED strip react to the sound.

I looked on many website to get informations on how can I make it, what I have learn is :

  • Audio is an AC signal
  • Arduino cannot work AC signal
  • A Peak to Peak circuit seems to be what I need, but I didn't manage to make it work...

I'm beggining in hardware I know few things in theory but I never build anything else than connecting an arduino to a LED strip, I hope you can help me.

Thank you.

There are many ways of allowing an Arduino to work with audio signals. Trying Googling "Arduino color organ". There are hundreds of them and they all react to audio either from a microphone or the input to a speaker/amplifier.

Or show us what you have tried and say what it does and doesn't do.

Steve

Thanks for your answer

I tried to look for "Arduino color organ" on google but I found only with microphone or audio jack as inputs... If you found one with speaker input I would like to check it .

I put some pictures of what I've made in the attachements, I tried to make a peak-to-peak circuit like here but maybe I missunderstood something ?

For the software I used the code I found in this guide

#include <Adafruit_NeoPixel.h>

#define PIN 6


Adafruit_NeoPixel strip = Adafruit_NeoPixel(30, PIN, NEO_GRB + NEO_KHZ800);

const int sampleWindow = 10; // Sample window width in mS (50 mS = 20Hz)
unsigned int sample;
int maximum = 110;
int peak;
int dotCount;
#define PEAK_FALL 4  // Rate of peak falling dot

void setup() 
{
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

void loop() 
{
   unsigned long startMillis= millis();  // Start of sample window
   unsigned int peakToPeak = 0;   // peak-to-peak level

   unsigned int signalMax = 0;
   unsigned int signalMin = 100;

   // collect data for 50 mS
   while (millis() - startMillis < sampleWindow)
   {
      sample = analogRead(6)*2;
      if (sample < 1024)  // toss out spurious readings
      {
         if (sample > signalMax)
         {
            signalMax = sample;  // save just the max levels
         }
         else if (sample < signalMin)
         {
            signalMin = sample;  // save just the min levels
         }
      }
   }
   peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
   
   int led = map(peakToPeak, 0, maximum, 0, strip.numPixels()) -1;
   
   for(int i; i <= led; i++)
   {
     int color = map(i, 0, strip.numPixels(), 0, 255);
     strip.setPixelColor(i, Wheel(color)); 
     
   }
   
   for(int i = strip.numPixels() ; i > led; i--)
   {
     strip.setPixelColor(i, 0); 
     
   }
  strip.show();
  
  if(led > peak)  peak = led; // Keep 'peak' dot at top
   
   if(peak > 0 && peak <= strip.numPixels()-1) strip.setPixelColor(peak,Wheel(map(peak,0,strip.numPixels()-1,0,255)));

   strip.show();
   
// Every few frames, make the peak pixel drop by 1:

    if(++dotCount >= PEAK_FALL) { //fall rate 
      
      if(peak > 0) peak--;
      dotCount = 0;
    }
    
}

uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
   return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else if(WheelPos < 170) {
    WheelPos -= 85;
   return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  } else {
   WheelPos -= 170;
   return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  }
}

void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

For now the LED strip is just flickering in the middle no matter how loud the sound is...

Still an audio signal going into a speaker, just lower impedance.

I tried to make a peak-to-peak circuit

Lets get the terminology right. What that circuit is, is a peak detector or envelope follower. It only follows positive peaks, nothing to do with peak to peak.

  • Arduino cannot work AC signal

Not true. An Arduino can only manage positive voltages not negitave ones. But if you add a DC bias to the AC signal then the Arduino is quite happy handling one. You make this DC bias circuit with two resistors and a capacitor.

tried to make a peak-to-peak circuit like here but maybe I missunderstood something ?

Yes you did. You have not got a common ground between your audio source and the rest of the circuit.

It is quite a poor page, apart from getting the name of the circuit wrong, you don't need that diode to ground, also there is no resistor across the capacitor on the right to control the discharge time. Better circuit is here:- Envelope detector - Wikipedia

Thank you for your help Grumpy_Mike

This is the envelope detector :

But I don't understand how to use it.
What are the two areas that I have circled into my circuit?

And how do I choose the values of the resistor and the capacitor ?

The area on the left is your audio input, connect it to your audio source. You have to have an audio in excess of 0.7V peak for it to start to work. The area in the right is your envelope output, connect that to the analogue input of your Arduino.

Make the capacitor 0.1uF and the resistor 10 K play about with these values until you get the responsiveness you want. The resistor controls the decay, and the capacitor controls the speed of following. They are not critical.

So I have to connect it like that ?

Yes, and you can add 10k output resistor to protect the Arduino pin from overvoltage, probably wise.

A schottky diode will reduce that 0.7V excess to around 0.4V if that helps, they have lower forward
voltages.

Adding 100 ohms or so input resistor would reduce any audible artifacts that this circuit might
produce in the speaker (limit the inrush current spikes).

Thank you for your answer, sorry I couldn't work on this project since last week.

The circuit seems to work, but the arduino is acting weirdly,
when there is nothing connected to A0 and GND the analogread() give me random values between 0 and 5V,
if I use my multimeter on it, the arduino stop reading random and give me 0V this seems legit,
but if I connect the circuit to the arduino I still get 0 with analogread() but with the voltmeter I get values different from 0V.

Any ideas of what is going on ?

when there is nothing connected to A0 and GND the analogread() give me random values between 0 and 5V,

That is perfectly normal. It is known as a floating input. It is picking up radio interference.

Adding your multimeter is pulling the input down and so that is stopping it from picking up interference.

A multimeter might be more sensitive that the analogue input. You need at least 4.5mV to register an analogue reading of one.