Sine Waves on Arduino: Variation

Today Ill be building on my Arduino Sine Wave Generator project. My goal is simple, to add the ability to dynamically change the frequency of the wave being generated. I should be able to read the value from a potentiometer similar to what was used in my original Arduino PWM post and write that value into the delay variable to modify the timing.

Wiring it Up

Arduino Function Generator Wiring

The wiring for this one is pretty straight forward and nothing we haven’t seen before. On the left is a potentiometer connected between 5V and ground. The wiper of this potentiometer is connected to analog pin A0 on the Arduino. This pin will provide an input value between 0 and 1023 depending on the position of the pot.

On the right we have the digital pin 5 connected through the same low pass filter I’ve used in previous projects. This will take our PWM output and smooth it into the final waveform.

The Code

The code only needs some slight modification from my last post. We need to first define the analog pin and read its value using analogRead. This is where some choices need to be made though. I mentioned that the analogRead for the potentiometer gives us a value from 0 to 1023. If we were to write this directly to the sample_time variable we would be producing some extremely long sine waves. Since our sine table has 50 entries this would mean at the highest setting each wave would take 51.15 seconds (1023*50/1000) to complete. That might be a bit much. So we need to decide how large a range we want to use and process the input accordingly.

I chose to divide the input by 16, this gives me a frequency range from about 10Hz to 0.313Hz. In the code you’ll notice I added a hard limit at 10Hz by adding 2 to the input value. This ensures the delay time never drops below a range that the Arduino and our filter can handle.


#define PWM_PIN 5            //PWM output at pin5
#define ANALOG_0 A0          //Input for sample_time
#define PWM_FREQ  980        //Hz
#define N 50

int sine_table[50];
int sample_time;
void get_sine_table();

void setup() {
  get_sine_table();
}

void loop() {
  for (int i = 0; i < N; i++){
    sample_time = analogRead(ANALOG_0);
    sample_time = (sample_time/16)+2;
    analogWrite(PWM_PIN, sine_table[i]);
    delay(sample_time);
  }
}

void get_sine_table(){
  for (int i = 0; i < N; i++){
    sine_table[i] = 127+127*sin(i*(2*3.14)/N);
  }
}

And there you have it! We can now adjust our frequency on the fly. Sorry it’s a bit of a shorter post today life’s been pretty full of late. Still I think this marks a pretty substantial step forward in this project. In my next post I’ll be looking at implementing the ability to produce more waveforms beyond just the sine.