Function generator with Arduino

felipearcaro:
Hey guys, I’m new here so sorry if my question is silly.

I’m trying to create a simple function generator with an Arduino Uno.

I’ve trying to play with two codes:


void setup()

{

pinMode(8, OUTPUT);

}

void loop()

{

// A total delay of 4 ms = 1/0.004 = 250 Hz…

digitalWrite(8, HIGH);

delayMicroseconds(2000);

digitalWrite(8, LOW);

delayMicroseconds(2000);

}


It’s a simple code, so I could understand how it works. I tried to create an RC filter in order to obtain a pure wave (instead of square wave).

I got a triangular wave and couldn’t get frequency values greater than 500Hz (delay~1000ms)

It is important to know what resistor and capacitor values you used. These determine the frequency border where the amplitude of higher frequencies start to get attenuated (reduced, I am assuming you talk about a low-pass filter). As you might know, a square wave is composed of a sine wave of the base frequency, with an essentially infinite sequence of higher (odd numbered) harmonics. A triangle wave is similar, but the higher odd harmonics are increasingly weaker and are alternately inverted (180 degree out of phase). So this looks normal for a square wave going through a RC lowpass filter.

However, these DigitalWrite commands have some execution time, and they are not always of the same duration. I used your code to generate square-waves on my Arduino Uno and looked at it with my analog oscilloscope. (No RC filter though, just the square wave) Your 2000 microsecond delays do result in about 240 Hz on my (uncalibrated) oscilloscope. The frequency counter mode of my multimeter reports 248 Hz. But with much shorter delay times the frequency seems to divert from desired. When the delays were set to 25 microseconds (20 kHz) I got about 17 kHz. Even with 2 microseconds I got a square wave, but not a sharp one, and far from the desired frequency. Can’t remember exactly, but I think 80 kHz, instead of 250kHz. So, do not rely on this method if you want reliable frequencies. Instead, direct control of the internal timer/pwm modes would get you better results.

This is the second code:


unsigned long t0;

void setup() {

pinMode(9, OUTPUT);

t0 = millis();

TCCR1B = 0x01;

}

void loop() {

analogWrite(9, (int) (255.0 * 0.5 *(1.0 + sin( (float) ((millis()-t0) % 1000) * 2.0 * 3.14 * 5.0 / 1000))));

}


In this case I could create the sin wave but I can’t either change it or measure it. I used the same RC filter.

My main objective with that is to get a sin wave which I can choose between 20KHz and 50KHz. I’m using ISIS Proteus as well, what allow me to create the filters and analyze the frequency.

Does anyone have some knowledge to help me with that?

Thanks.

I tried this also and could get a signal that looked like a sine wave, but actually looked like 2 on top of each other on my oscilloscope screen (AC-coupling). Your mathematical levelshifting and turning the result into an int isn’t working right. It still generates values higher than 255, which overflow in the AnalogWrite funtion (or PWM timer) to just above 0. Make sure you test which numbers it generates by sending it to the serial monitor. Anyway, the sine was so slow that I could not get a steady image. So I do not have a frequency measurement.

On that note however, the use of floating point operations, and trigonometry functions like sines and cosines is notoriously sloooooooooww. Calculating them for audible frequencies is not the appropriate way. It would be better to use lookup-tables to take the sine value of a certain phase angle. Even with those methods generating frequencies in the 10-100 KHz range is unlikely. You really need to resort to quick compact machine code for that. No go with Arduino functions.