Arduino Waveform Generator

Program Download:

Arduino Code
Function_Generator.ino

The Software
           There are three main parts to the firmware for this project:
    -The Arduino Setup
    -The Arduino Loop
    -The Arduino Interrupt Service Routine

The first part of any arduino program is the setup function. This occurs before the loop which continually executes forever. The setup portion of the code is meant to be run only once, so you should setup variables, interrupts and all hardware modules that you will be using. In our setup() function, you can see we setup the outputs and inputs for data latches, then we setup the timer interrupt and finally we initialize some variables to get standard values for the arduino.

The Arduino Setup

------------« Begin Code »------------
..
...
void setup() {
  
  //set port/pin  mode
  DDRD = 0xFF;//all outputs
  DDRC = 0x00;//all inputs
  DDRB = 0xFF;//all outputs
  //TIMER INTERRUPT SETUP
  
  cli();//disable interrupts
  //timer 1:
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  //set compare match register- 100khz to start
  OCR1A = 159; // = (16 000 000 / 100 000) - 1 = 159
  //turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS10 bit for 0 prescaler
  TCCR1B |= (1 << CS10);
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A); 
  
  samplerate = 100000;
  
  PORTB = 0;
  PORTB = 1<<type;
  
  //initialize variables
  frequency = analogRead(A5);//initialize frequency
  freqscaled = 48*frequency+1;//from 1 to ~50,000
  period = samplerate/freqscaled;
   
  pulseWidth = analogRead(A4);//initalize pulse width
  pulseWidthScaled = int(pulseWidth/1023*period);
  
  triInc = 511/period;
  sawInc = 255/period;
  sinInc = 20000/period;
  
  sei();//enable interrupts
}
...
..
------------« End Code »------------

The main loop for any firmware should be small with only the basic functions included. In the main loop here you can see 3 functions are run to check if any of the inputs have changed and to act accordingly. Download the full source code above to see what exactly these functions do.

The Arduino Loop

------------« Begin Code »------------
..
...
void loop() {
  checkFreq();
  checkShape();
  checkPW();
  PORTB = 1<<type;
}
...
..
------------« End Code »------------

The most important part of the code is the ISR or interrupt service routine. In the setup function we made it so that a timer would interrupt the main loop at a common interval, so that we can execute some additional code in case there are input changes. This interrupt service routine is where that additional code is and if you look through it you'll see a big switch statement that acts according to whatever type of waveform we should be currently outputting.

The Arduino Interrupt Service Routine

------------« Begin Code »------------
..
...
ISR(TIMER1_COMPA_vect){//timer 1 interrupt
  //increment t and reset each time it reaches period
  t += 1;
  if (t >= period){
    t = 0;
  }
  switch (type) {
    case 0://pulse
    if (pulseWidthScaled <= t) {
      wave = 255;
    }
    else{
      wave = 0;
    }
    break;
    case 1://triangle
    if((period-t) > t) {
      if (t == 0){
        triByte = 0;
      }
      else{
        triByte += triInc;
      }
    }
    else{
      triByte -= triInc;
    }
    if (triByte>255){
      triByte = 255;
    }
    else if (triByte<0){
      triByte = 0;
    }
    wave = triByte;
    break;
    case 2://saw
    if (t=0){
      sawByte=0;
    }
    else{
      sawByte+=sawInc;
    }
    wave = sawByte;
    break;
    case 3://sine
    sinNum = t*sinInc;
    wave = pgm_read_byte_near(sine20000 + sinNum);
    break;
  }

  PORTD = wave;
}
...
..
------------« End Code »------------

           Enough code and firmware, use a usb cable to load the firmware onto the Arduino UNO using Arduino software, then get testing to see how the waveform generation works! On the next page we'll show some demonstrations of the waveform generator working.