Variable Sine Generator


I've always wanted a low-frequency sine generator but the RampPulseGenerator has always served as a better test oscillator up until now. After building the ServoPushrodModelAirplaneStand I've felt renewed need for something more gently swaying.

Approach

One strategy would be to build an arbitrary function generator that worked by table lookup. I chose instead to implement a feedback loop that just happens to oscillate.

   dx = f(y)
   dy = -f(x)

Here is perl code that approximately solves these equations iteratively using 16-bit arithmetic.

   ($x,$y)=(32000,0);
   for(0..3200){
      $x+=int($y/256);
      $y-=int($x/256);
      print "$_\t$x\t$y\n";
   }

This script shows the period to be just over 1600 iterations. If an iteration were repeated with each bynase pulse output then it would run at around 10 Hz.

Implementation

I coded up the generator Saturday morning. I was hoping to have it running my plane as a show-off item at BarCampPortland. But the darn thing didn't work. It produced a sawtooth wave, not a sine. Hmm. What could be wrong.

One day later ...

I figured out what was wrong with my oscillator. I forgot that I had to sign-extend the hi byte when I used it as a lo byte. It is as if I confused LSR and ASR when shifting to divide.

Frequency Control

I added frequency control by slowing down the rate of iteration. I bump an 8-bit register with pi and continue with the iteration only when I get a carry-out.

Output frequency is proportional to input with a max freq of about 5 Hz. The plane looks great rocking back and forth at about 1/4 Hz. My stand resonates side-to-side at about 3 Hz and front-to-back at 4 Hz.

When input goes to zero, the output holds at what ever value it last had. I'm using the knob that use to rock the plane to now control the rocking frequency. I can still pose the plane by just rocking slowly and then twisting the knob to zero when it is in the position I desire.

Amplitude Control

I set the amplitude when I assemble the program. The amplitude is stable once set. Frequency varies by a few percent at all but the lowest amplitude. I could set the amplitude from input by just resetting x as y crosses zero.

I'm sure I will find lots of uses for both frequency controlled and amplitude controlled parts.

Code to follow soon.

 

Last edited May 4, 2008
Return to WelcomeVisitors