dds sine wave frequency changing

no i understand how dds works, the website about it made by the KHM is great for learning the basis.
now you're right about the code implementation, i am lost with some part of the code but the general idea about interrupt and DDS is clear for me. i understand more the theory side than the code process.
when i said to you that your code suggestion works as my previous attempt, it's real. i tried both your code and mine, same result in the speakers, same strange quiet noise. obviously i prefer your code because i know that my version comes from some hazardous trial and errors testing (as a layman :)).
now even if don't understand all the code it should work as its is without this noise.
if i can make this working correctly i will purchase the understanding of the whole code. maybe you want to hear the result, i attach a record, you can hear clearly these strange notes in the background. maybe
this problem comes more from aliasing than from the code (i use a RC filter but maybe it's not enough) ? i don't know how aliasing does sounds like...

thanks for your help.

strangeNotes.wav (3.67 MB)

The noise you're referring to - is it that warbling that starts at about three seconds into the recording?

I wouldn't call that noise - it is the output frequency changing. That implies that you have calculated a new value for the frequency, presumably because analogRead() has returned a new value.

did you hear two distinct sounds in this audio file ? on the foreground we can hear the sinewave sweeping (it's what we want) but if you listen carefully you will notice that there are some others notes in the background. these random notes are audibles (quiet at first) since the begining of the recording but there are louder at 3sec until the end. maybe you have to increase the volume a bit. it sounds like a quiet echo of randomly triggered notes.

i tryed to decrease the cut off frequency of the RC filter but it doesn't change anything.

Are you referring to that really, really quiet noise that is almost impossible to make out (on my speakers) in the background? As if there were brief bursts of pink noise being introduced.

yes !!! it's not noise you can hear quickly triggered but distinct tone. the more the sensor is excited the more you will hear this strange echo in the background.
maybe it comes from the response time of the rc filter ? i don't have the components to test the chebyshev
filter...

If you look at the WAV file with an audio editor (I use GoldWave) you can see that your sketch isn't generating a clean sine wave and the spectrum of the wave has harmonics all over the place.
The peaks of the waveform are almost flat which I think is caused by the low resolution of the sine wave table. Note, for example, that there are six consecutive zeroes in the table which correspond to the negative peak of the waveform. There are seven consecutive occurrences of 254 which correspond to the positive peak.

Pete

yes you're right i checked this into audacity... but the sketch comes from this website and they seems to obtain a great sinewave with a clear peak at 1000hz (frequency test) :
http://interface.khm.de/index.php/lab/experiments/arduino-dds-sinewave-generator/

so maybe the problem is less the resolution than the RC filter smoothing, i need to try with their chebyshev filter... maybe my RC filter is too slow in response time ?
i added another pole, so i've got two poles in series but it doesn't make a big change...

i just have tried this another code from adam freed :
http://adrianfreed.com/content/arduino-sketch-high-frequency-precision-sine-wave-tone-sound-synthesis

this code is a good example because there are variation in frequency. the sound result is the same we can hear the same noise in the output...

That code uses essentially the same sinewave table and DDS technique so it's going to produce the same audio. I think you'll have to work on your audio filter to improve the sound.

Pete

yes it's exactly what i plan to do. i have to order some inductors for the chebyshev lowpass filter.
so i've got to wait... i give up the RC filter.

Looking at the .wav file with Audacity, I think that the waveform is clipped, and slew-rate-limited. Looks like there's trouble on the analog side. I don't think that you've gotten the project to a point where it will really help much to add a complicated filter on the output. I'd suggest fixing it as best you can before you go to that effort.

Here's what I undestand about your project, based on what you've told us so far:

  • Looking at what I think is your code - from the link you included with your original post - it appears that your output data range from 0 to 254. That corresponds to a time-averaged output voltage ranging from 0 to nearly 5V, or almost full-scale for a 5V system.

  • You're using an RC filter on the output: 330 ohms and 0.01 uF. I presume that the resistor is connected between the output pin and the capacitor, and that the capacitor is connected between the resistor and ground. I also presume that the audio output is taken from the junction of the resistor and the capacitor. That output filter will have a cutoff frequency of about 48 kHz, and it won't noticeably attenuate the frequencies that you're interested in, which range from 440 Hz to about 1.5 kHz - and those figures are based on the code you linked with your first post, rather than the code that you've pasted into your posts. It's worth noting that a this filter won't attenuate the 32 kHz PWM signal very much, either. It's not clear to me that it's doing much good.

  • You're using an LM386 to amplify the output, but you haven't described how it's hooked up. I presume that it's connected to provide a gain of 20, because that configuration uses the fewest parts, and that you're powering it from 5V and ground.

  • You recorded the wav file that you posted using a speaker and microphone, rather than directly connecting the filter output to a recording device. I don't see much of the PWM signal in the file, so I suspect that the whole circuit - including the LM386, the microphone, and the recording input - attenuate that signal quite a lot.

So, it looks like you're using a 5V peak-to-peak signal to drive an amplifier with a gain of 20, and a power supply of 5V. The amplifier can't deliver 20 times the input voltage under those conditions, so the output is clipped.

The LM386 has an input resistance of 50k ohms, so a quick way to get the output signal into the linear range is to connect a 1M ohm resistor between the output of your filter and the input of the LM386. The voltage divider formed by the 1M ohm resistor and the 50k ohm internal impedance of the LM386 will attenuate the input signal by a factor of 20, and the amplifier won't be forced to clip the output signal. You might be better off with a 1.2M ohm resistor. Either way, the impedance of the 1M+ ohm resistor is much higher than the filter's impedance, so it won't affect the filtered output in any noticeable way.

I believe also that you'll get better results if you use an output filter with a lower corner frequency. I'd suggest a frequency of maybe 6 kHz - two octaves up from the highest frequency you'll output, and 2+ octaves below the PWM frequency. As it stands, your output filter passes the PWM frequency almost unaffected. Maybe change the 330 ohm resistor to a 2.5k ohm resistor.

In the wav file, the regions between the flat-tops show a nearly constant slope, but it's too shallow to correspond to a sine signal with the same frequency as the wave in the file. That leads me to believe that the output is also slew-rate limited. The LM386 datasheet doesn't describe a slew rate. However, the data in the wave file are pretty much what I'd expect to see for an overdriven, slew-rate limited amplifier. Reducing the input signal, as described above, will help a lot with the slew rate - it'll reduce the rate by a factor of 20.

Try that, and see if you don't get some improvement. I believe that you'll hear only a small loss of volume, but a much clearer sine output.

I've made a lot of assumptions, and those could be wrong. But, we don't have much information to work with. I'll note, though, that the wav file provides a lot of insight into your system, and we'd have never gotten it from a verbal description of the audio. I'll also note that the audio doesn't sound bad at all, and it sounds to me that it's doing what you wanted it to do. I'd have thought that the effect you describe was an artifact of the recording technique. If I'd built this project, I might be calling it a success by now.

ok i added the resistors and put a cut off frequency at about 16khz, clipping is gone and the spectrum of the sinewave is better. the sound output is far better, the sinewave is purer but noise remains the same... same crazy noise...
i tried with a factory made amplifier/speaker and it's the same, so it doesn't comes from my LM386 based amplifier circuit.
sorry about the lack of precision, i recorded the sound with the line input of an external soundcard.
jack out of the LM386 -> input line (soundcard). noise doesn't come from the recording process.
so i tested some simple triangle LFO like this and the result is good, less noise, it sweeps the frequency up to 8000hz (a record is joined):

cpt=cpt+(1direction);
if(cpt>8000)direction=-1;
else if(cpt==0)direction=1;
dfreq = (cpt
10);

then i tested a code which triggerred some random notes with some linear interpolation to fill in between the notes and noise came back...

sweeping0hzupTo8000hz.wav (1.79 MB)

I'm delighted to hear that there's improvement.

I've been unable to identify the extraneous sounds you're talking about. I may hear a bit of hiss in the background, but I'm not sure that that sound is what worries you.

The wav file looks great. If you want improvement on that, it's possible that a better filter will help; it's also possible that it won't. I can't predict.

You may want to look into using op amps to develop a multi-pole filter. Inductors are hard to find in precise values, and they continue to be a annoyingly non-theoretical. One of the favorite aspects of op-amp filters is that you can implement a two-pole filter without using inductors. Texas Instruments publishes a program that will do the laborious math of filter design. You can find it here: Filter Designer | Design Resources | TI.com.

i made another recording, maybe you will hear it. it sounds like some randoms notes delayed in the background. as soon as i have the component (few days), i will try the chebyshev filter, it will be the last chance. the sound of the sinewave is great but this noise echo is too audible. i can't use this for audio. maybe i should use a DDS module like AD9850 or something like that. your suggestion with texas instrument filter is interesting but i think i'm overthinking this project, i 'm spending too much time on it. nevertheless you help me a lot, thank you for your patience ! i would like to pay you a beer :slight_smile:

thanks everybody

noiseT.wav (2.14 MB)

OK, I hear two things: some hiss, and some soft, changing musical tones. The tones seem to alternate from something less than a whole tone below the foreground note to maybe about a minor third above it. The pattern seems to repeat. Those tones are very faint, though, and I could be wrong about their pitches.

I'll suggest that you try recording a couple of seconds of audio four ways, as an experiment:

  1. With the Arduino connected, and running its program, with the output pin's mode set to output, but with the PWM turned off
  2. With the Arduino connected, and running its program, with the output pin's mode set to input, with the PWM turned off
  3. With the Arduino connected, but with its power supply disconnected, and
  4. With nothing connected. You may have to plug in a cable to the sound card to convince it that something's there.

if you're feeling especially curious, you could try letting the PWM run, and connecting the output to a different, quiescent digital output, and then to a quiescent digital input, and see what happens then, too.

I won't ask you to post those files, because that amounts to a whole lot of data. But, I'll ask you to listen to them, to find out whether those effects are showing up without the PWM operating. I'm thinking that they may artifacts of the programs running on the Arduino or the PC, or of the power supply.

The Arduino's power supply will likely have switching components, and they may switch in a fashion that makes some audible artifacts on the output signal. Remember - the digital signal isn't perfect; excursions on it's power supply will affect the output voltage. Those excursions may come from the power supply itself - probably a PC's USB port; from short-term variations in the power supply voltage caused by current drawn by the Arduino; or from the PC power supply that drives the sound card you use to record. I note that the sound card you're using is external, but I'm not sure that means that its power supply is isolated from the PC. Is it USB-powered?

The hiss that you hear may be filterable, but the tones are right in the range that your low-pass filter has to let through. It seems unlikely that you'll be able to filter them out, while leaving the actual output audio signal unaffected.

No need to post files. We'll rely on your ears.

how do you turn off the PWM ? i noticed that there is sound on the output pin around pin11. it's the PWM
signal but at very low volume. then we can hear some noise on pin6. i'm working on breadboard, maybe
this noise comes from there ?

i have an ATtiny85 maybe i can test the sketch on it ? or it's too complicated ? i know how to upload
sketch on it but the syntax seems to be different for timer interrupt.

polish:
how do you turn off the PWM ?

PWM is started by analogWrite(), and can be ended by digitalWrite(). It would also be ended by analogWrite(0) or analogWrite(255).

PeterH:
PWM ... can be ended by digitalWrite(). It would also be ended by analogWrite(0) or analogWrite(255).

Indeed. I can't vouch for digitalWrite(), having never tried it. But analogWrite'ing 0 or 255 would do it. In fact, it would be interesting to see if things change between analogWrite(0) and analogWrite(255) - one drives the output close to ground, and the other near Vcc - I'd want to bet that analogWrite(0) would yield a quieter output. Or, you could just comment out all the analogWrite()'s altogether.

Remember, you've got a whole lot of digital activity going on in the Arduino and in the PC, and even in the sound card. All of that activity influences Vcc, however slightly, and that influence won't typically be harmonic with your output signal, making it easy to hear. My favorite theory right now is that you're hearing audible components of power supply noise, influenced by all that digital activity.

As to whether the breadboard could be a problem: It's not much of a noise source in itself, though it might pick up some ambient electromagnetic fields. I think it's more likely that using the breadboard means that you use long, loose wires to connect the components. I've seen the performance of a number of analog projects improve when I replaced pre-cut jumpers with cut-to-length telephone wire. Loops of wire act like antennas, and, probably worse, have a higher impedance than short wires or printed-circuit traces, leading to small but noticeable voltage drops across them.

You might get improvement by using single-point grounding. Bring a ground from the Arduino to a convenient spot on the breadboard, and then run every other ground to that same point. We sometimes want to think of every ground as being exactly the same; however, when we run a ground from one device to another in daisy-chain fashion, we accumulate current - and hence unwanted voltages - in the chain of conductors. I've seen analog circuits improve, sometimes considerably, when I reminded myself to do this.

Finally, I encourage you to use power-supply decoupling capacitors very close to any analog components that draw power from the supply, like the amplifier IC, if you don't have them already. I'd recommend an electrolytic and a ceramic capacitor in parallel - maybe a 10 uF and a 100 nF. Texas Instruments' datasheet for the LM386 quotes a power supply rejection ratio of 50dB, but mentions that the test is performed with a 10 uF bypass capacitor. I can't quite do the math just now to figure out whether 50dB of rejection is really good enough for this application. Bypass capacitors might not help much, or they might make a huge difference, depending on the actual source of your unwanted signal.

The reality is that you're trying to get very good analog performance from a digital circuit. That's not typically as easy as we'd hope - you have some work ahead of you.

polish:
... I think I'm overthinking this ...

You're overthinking it? I'm defenitely overthinking it, and it's not even my project.

You haven't said whether the power to your analog section is the same supply that runs the Arduino. Is it?

1/ nothing to hear.
2/same
3/same
4/same
grounding everything at the same point didn't change anything.

i tried to output PWM directly from pin11 without using the breadboard and noise remains. so it
seems to not come from the breadboard.

i made a test with another power supply for the arduino and nothing changed (9V battery).

yes LM386 power comes from the arduino 5v.

Have you considered passing those sample values to something on the PC that can generate the corresponding audio output, and see whether the noise was caused by the sample data or an artifact of the Arduino output process?