Shouldn’t the two methods to toggle the speaker pin generate exactly the same square wave?
On an oscilloscope, they do look very similar, although the method of changing the PWM duty cycle looks slightly more unstable, i.e. it doesn’t trigger as well.
Find the full code attached, tested on an original SparkFun Arduino Pro Mini (16 MHz, 328P).
I now had a closer look at the oscilloscope, and I believe I understand what’s going on. The problem seems to be that PWM pulls pin 3 high always when starting a new wave. I need to look at the 328P data sheet to understand how to deal with that. Maybe switching to inverting mode only when the signal is supposed to be zero is a solution.
With this modification, the sound is good, well as good as a 4 kHz square wave can sound.
Now I can change the volume by applying PWM to the non zero pulses. Alternatively I’m thinking about increasing the sampling rate and adjusting the duty cycle. That doesn’t give me as high resolution, but I will save one timer.
Depending on the exact operating mode, a PWM timer will only apply the OCR
(output compare register) change at a fixed point in the PWM cycle - this frequency
will be beating against the ISR frequency to create artifacts. If you synchronize the
ISR to the PWM waveform correctly, these artifacts would vanish.
The ear is a fairly sensitive spectrum analyzer and picks up spurious tones very easily.
MarkT:
Depending on the exact operating mode, a PWM timer will only apply the OCR
If you synchronize the ISR to the PWM waveform correctly, these artifacts would vanish.
Thanks for pointing out this source for noise! If I understand correctly what you wrote, then I did have a different problem, which I solved as described in post #2: Even with an empty duty cycle (OCR2B = 0), the output pin is briefly pulled high at the beginning of every PWM pulse. This can be seen in the output on the oscilloscope.
The ear is a fairly sensitive spectrum analyzer and picks up spurious tones very easily.
I realize, LOL. Although this particular issue has been solved, in the end I decided not to use PWM to modulate the signal. I output to tiny magnetic buzzers, and they already sound very thin.