# Variable frequency PWM

I’m currently using a Deumilanove to generate PWM pulses out of Digital pins 5 and 6 to generate an unfiltered sine-wave (for inverter). At beginning of program execution I calculate on and off times for 20 divisions within each half-wave, then during looping phase I simply turn pin on and provide a pre-calculated on-time, then a pre-calculated off-time for each time-division within each half-wave. Works great, results in continuous 60 Hz sine wave.

What I now want to do is control frequency btw about 20 Hz. and 120 Hz. by feeding an analog input (0-5 VDC) into one of the Analog input pins. If I simply perform an analogRead at end of each cycle, then recalculate all on and off times at beginning of next cycle, I fear I’ll create a delay between each cycle that won’t work for my motor. Does anyone have a better idea of how that can be done or can it be done at all?

The on and off times scale linearly with the frequency, so the only thing that need change as the frequency changes is a single scale factor.

Surely you can fit in 20-40 multiply operations per AC cycle, so that the same number of operations is performed regardless of frequency.

If you’re a bit careful to use only integer math, you can do a calculation in a handful clock cycles (so within 1 µs). Floating point math you should really avoid here, that takes a lot longer.

Try to make your wave division factor to fit in a multiple of 2, so not 20 divisions per half wave, but 16 or 32. This way you can use bit shifts for divisions/multiplications, like this:

``````// Division:
result = value / 32; // is the same as:
result = value >> 5;

// Multiplication:
result = value * 16; // is the same as:
result = value << 4;
``````

Those bit shift operations take less operations, making your code even faster, so you can do 32 divisions for a half wave (64 for a full wave, times 120 Hz, 7680 calculations per second so you have 130 µs per calculation).

Furthermore you should look into direct port manipulation, which is much faster than using the digitalWrite() function.

Don’t read the analog pin too often as you may mess up your waveform: an analogRead() takes quite some time.

Thanks so much guys!!! I never thought of any of those ideas (not a programmer as you can tell). AWESOME!!!!