Nerveware


Sine wave

So after some long hours, I finally finished my school assignment. Due to its awesomeness, I've decided to write a document about it in which I will describe the process of generating a sine wave. Before you start, you'll need equipment:

The scheme

Connect A0 to the middle potentiometer pin (pins facing forward). Left to 5V and the last to GND. Connect the MSB ladder resistor to your oscilloscope (+) and the 9 following from as followed on your Arduino:

Registers

To everybody owning an Arduino, the function pinMode will sound familiar. This function configures read or write access to the given pin.

pinMode(1, OUTPUT);

The same can be done to the eight connectors directly through the registers. Using these registers speeds up your program, but it's kind of tricky sometimes. The Arduino has the following register letter prefixes.

  1. B = digital pin; 8 to 13
  2. C = analog pin; A0 to A5
  3. D = digital pin; 0 to 7

A register is divided into three parts. Below, "x" is one of the letters above

  1. DDRx = Data Direction Register
  2. PORTx = Read/write
  3. PINx = Read only

In out code we need pins 2 to 7, thus PORTD, set as output. We will use the pin definitions for this port and place is into a function.

void port() { DDRD |= ((1<<DDD2) | (1<<DDD3) | (1<<DDD4) | (1<<DDD5) | (1<<DDD6) | (1<<DDD7)); }

Timers

Timers are very useful for every program which must execute code periodically. First, we'll disable the PWM on the TCCR1A register. We toggle the waveform generation mode on register TCCR1B and use the system clock as timer. The TIMSK1 and TIFR1 ports are used to control which interrupts are valid, and thus we'll enable OCIE1A and OCF1A.

void timer() { TCCR1A = 0; TCCR1B = (1<<WGM12); // Waveform Generation Mode 12 (or CTC1) TCCR1B |= (1<<CS10); // Clock Select 10 // timer interrupts TIMSK1 = (1<<OCIE1A); // Output Compare Interrupt Enable 1 A; TIFR1 |= (1<<OCF1A); // Output Compare Flag 1 }

So far for the setup. Lets define the timer itself.

ISR(TIMER1_COMPA_vect) { PORTD = (sinetable[i]);// | 0x3); i = (i >= 360) ? 0 : i + 1; }

More information about the Amtel ATmega328, download the datasheet.

The sine

The calculation for the sine is the last part of this article. Because our range is from 0 to 255 and a sine wave has negative values, we need to set a fictional "0". The new "0" will be the half of 255.

void sine() { for (int i = 0; i < 360; i++) { sinetable[i] = sin(i * 3.14157 / 180.0) * 127.5 + 127.5; } }

You should be able to figure out the rest yourself. For those too lazy to do this, the full code is onto the next page.