Sound distorts/clips when using the tone function. (SOLVED)

Problem solved; TLDR version: the tone function is not good enough to create fast pitched sounds. Using the toneAC library which uses timer1 solves this problem -> Google Code Archive - Long-term storage for Google Code Project Hosting.

Hi!

I am building a sound generator using an Arduino Uno and the tone() function.

Here is the code

const int speakerPin = 11;

const int buttonOne = 6; 
int buttonStateOne = 0;


const int potOne = 0;
int potOneVal = 2; 

const int potTwo = 1;
int potTwoVal = 100;

     

void setup(void) {  
  Serial.begin(9600);
  pinMode(buttonOne, INPUT);    
  pinMode(speakerPin, OUTPUT); 

}

void loop(void) {

  potOneVal = map(analogRead(potOne), 0, 1023, 200, 1000);
  potTwoVal = map(analogRead(potTwo), 0, 1023, 100, 1000);
  
 
  buttonStateOne = digitalRead(buttonOne);

  if (buttonStateOne == HIGH ) {
    sirenSlow();
    delayMicroseconds(25);
  }

}

void sirenSlow() {
  int i = 0;
  while(i < potOneVal) {
    tone(speakerPin, potTwoVal+i);
    i++;
  }
  noTone(speakerPin);
  while(i != 0) {
    tone(speakerPin, potTwoVal+i);
    i--;
  }
  noTone(speakerPin);
}

What I am trying to achieve is a siren like sound which works almost perfectly now except that the generated sound clips, pops or distorts (see this small recording I uploaded to youtube)

You can hear that the sounds is clipping or popping. The reason could be is that the Arduino generates a pure SquareWave and I send it to the speaker, and because the signal is too loud or harsh it clips in my speaker. I tried to counter that with adding resistance but without success. I also created a very simple amplifier using a LM386 but also without success.

When I generate a pure tone() (without loops) I don't hear the clipping, even when I add a sequence of tones (with enough delay) I still don't hear the clipping so the problem is within the loop perhaps? Maybe the tone() gets fired to quick which generates the clipping/popping. I've tried to counter that with delays within the while but that generates weird / distorted noise.

Current flow: arduino uno via monojack to my analogue mixingdesk to my active Yamaha80SM speakers.

I'm kinda out of ideas at the moment, any ideas?

Thanks!

// edit

The clipping/popping is almost only noticeable when the tone generates a high frequency but I am sure the same problem occurs also on lower frequencies but not noticeable enough.

// more edits

when I send the signal with only a resistor to my mixing desk the incoming signal clips but the sound is good except for the popping/clipping, when I use a LM386 simple amplifier circuit to create a clean signal for a mixer the incoming signal on the mixing desk does not clip and is lower in volume (which is good!) the clipping/popping does not dissapear though and is still very noticeable

I've found a lead that low pass filtering could provide a solution to my problem because this method creates an analog signal from a PWM signal and lowers to signals amplitude. This gives the mixingdesk/speaker also the negative voltages to amplify and makes the signal less clipped which results in a pure undistorted audio signal.
Is this true?

A low pass filter will make a big difference for the better, but they are frequency selective. A simple RC filter will reduce the amplitude of signal frequencies above its "knee" frequency of 1(2PIRC), so you need to choose R and C values appropriately. It will not eliminate the DC offset, for that you need a bandpass filter (combination of low pass and high pass).

One place to start reading is here: Filter Circuits with Capacitors

Edit: corrected link

Cheers! I'll read it.

Currently watching a lot of videos/guides on RC Low Pass Filters and it looks like the solution to my problem. I will create a test circuit tomorrow to try it out.

I've tried the RC Low Pass Filter. No success. I hear that the sound is filtered but the clipping/popping sound is still there.

Any other ideas?

What values for R and C did you use, and what tone frequencies are of interest?
Are you driving a speaker directly, or using an amplifier? If the latter, post the circuit diagram.

For best results, use a suitable RC bandpass filter. Two resistors and two capacitors, as follows: http://www.electronics-tutorials.ws/filter/filter_4.html

Hi jremington

I have calculated the LPF for 2kHZ, can't recall the R & C values exactly now but I hear the higher tones being lower in volume. I am using active amplified speakers (Yamaha HS80M) fed from a analog mixing desk (the arduino is plugged in using a mono jack).

The goal is to create a mini synth which can be hooked up to a DJ mixer for sound effects..

Ive tried to route the signal from the digital pin to a voltage divider which dives the voltage to 2.5v, then route it to a LPF on 2kHZ and then amplify the signal with an LM386.

see this image

though I have the idea the audio is way phatter and sounds better the distortion still occurs, I am afraid the arduino is not capable of generating different tones within a loop.

I think this is just not possible without clipping/pops

// potOneVal can be anything between 100 and 1000
// potTwoVal can be anything between 100 and 1000

  int i = 0;
  while(i < potOneVal) {
   tone(speakerPin, potTwoVal+i);
    i++;
  }

I'll see and try the band pass filter tomorrow

Thanks for the tip!!!

Unless you can post a circuit diagram with component values, no one will be able to help further. Avoid Fritzing diagrams.

I would use an oscilloscope to make sure that sine waves of the correct amplitude are being presented to the amplifier/speaker. Otherwise, expect distortion.

Problem solved; the tone function is not good enough to create fast pitched sounds. Using the toneAC library which uses timer1 solves this problem -> Google Code Archive - Long-term storage for Google Code Project Hosting.