Это простой функциональный генератор с регулируемой частотой работает в диапазоне звуковых частот. Он может быть полезен для тестирования усилителей, экспериментов в области цифровой обработки сигналов и в лабораториях электроники.
Авторский прототип представлен на следующем рисунке:

Принципиальная схема функционального генератора
Схема содержит плату Ardunio Uno (Board1), ЖК-дисплей 1602 (LCD1), два потенциометра по 10 кОм (VR1, VR2) и несколько дополнительных компонентов.
Потенциометр VR1, подключенный к контакту 3 LCD1, используется для управления контрастностью LCD1. Потенциометр VR2, подключенный к выводу A0 аналогового входа платы Arduino Uno, используется для настройки периода времени выходных сигналов (частоты).
В качестве выходов использованы контакты 3, 9 и 10 платы Arduino:
- контакт 3 — для прямоугольной волны
- контакт 9 — для синусоидальной волны
- контакт 10 — для пилообразной волны
Сигналы с выводов 9 и 10 фактически являются широтно-импульсными модулированными (ШИМ) сигналами, несущими аналоговые сигналы. Необходимая форма сигнала получаются с помощью простой схемы резистивно-конденсаторного фильтра. Прямоугольный сигнал на выводе 3 снимается без фильтра.
Эти формы сигналов синтезируются с использованием функций управления прерыванием Timer0 и Compare-Match микроконтроллера Arduino (ATmega328). Таймер1 ATmega328 запрограммирован на частоту 10 кГц для генерации выходных сигналов ШИМ.
Переключатель S2, подключенный к контакту 8 платы Board1, используется для изменения частотного диапазона. В программе предусмотрено два частотных диапазона: от 30 до 250 Гц и от 250 до 2500 Гц для покрытия среднего диапазона звуковых частот. Эти сигналы от CON2 до CON4 можно просмотреть на осциллографе.
Скетч функционального генератора
#include <LiquidCrystal.h> int ledPin = 13; // Светодиод подключен к цифровому выводу 9 int analogPin = A0; //потенциометр подключен к аналоговому выводу 3 int val = 0; // переменная для хранения прочитанного значения //int data[32]={200,238,278,310,341,366,384,396,400,396,384,366,340,310,276,238,200,162,122,90,59,34,16,4,0,4,16,34,60,90,14,162}; int n=0; int data[24]={125,157,188,213,233,246,250,245,233,213,188,156,125,93,63,37,17,4,0,4,17,37,63,93}; int P; boolean k; unsigned int freq; //int data[32]={125, 149,174,194,213,229,240,248,250,248,240,229,213,194,173,149,125,101,76,56,37,21,10,3,0,3,10,21,38,56,76,101}; int(y)=1; int (sig)=1; int freq1; LiquidCrystal lcd(12,11,13,4,5,6,7); void setup() { pinMode(ledPin, OUTPUT); // устанавливает вывод как выход pinMode (9,OUTPUT); pinMode (10,OUTPUT); pinMode(11,OUTPUT); pinMode (12,OUTPUT); pinMode(8,INPUT_PULLUP); pinMode(2,INPUT_PULLUP); cli(); TCCR1A = _BV(COM1A1) | _BV(COM1B1) ; //TIMER1 PWM MODE TCCR1B = _BV(WGM13) | _BV(CS11);//8 PRESCALER ICR1=250;//4000Hz //установить прерывание таймер0 TCCR0A=0; TCCR0B=0; TCNT0=0; //инициализировать таймер0 //OCR0A=12; //timer on, TCCR0A|=(1<<WGM01); // установить бит для предварительного делителя // TCCR0B |= (1<<CS00)|(1<<CS01); TCCR0B |= (1<<CS01); //Включить прерывания от таймера TIMSK0|=(1<<OCIE0A); Serial.begin(115200); lcd.begin(16,2); //delay(1000); lcd.setCursor(0,0); lcd.print("freqency Hz"); //delayt(300); sei(); } void loop(){ //int sig=1; val = analogRead(analogPin); // прочитать входной контакт val=val/4; if (val<33)//35 to 240Hz {val=35; } freq=8533/val; freq1=freq; if (digitalRead(8)!=1){ freq1=freq *10;} if (digitalRead(2)!=1){ for (int g=1;g<freq/18;g++){ Serial.print(data[sig]/3+150); Serial.print(" "); Serial.print((sig)+100); Serial.print(" "); Serial.println((sig/16)*10+75); } sig=sig+1; // delay(2); if (sig>23) {sig=0; } } else { ICR1=250; lcd.setCursor(0,2); lcd.print(freq1); lcd.print("Hz"); } } void plot() { //while (digitalRead(2)==1){ cli(); Serial.print(0); Serial.print(" "); //Serial.print(200); Serial.print(" "); Serial.print(data[sig]/3+300); Serial.print(" "); Serial.print((sig)+150); Serial.print(" "); Serial.println((sig/16)*10+50); sig=sig+1; delay(2); if (sig>31) {sig=0; } sei(); } ISR(TIMER0_COMPA_vect){ //read data(n) k=digitalRead(8); //digitalWrite(13,k); if (k==1) { OCR1A=data[n]; //sine OCR1B=n*8;//ramp wave if (data[n]>=125) { digitalWrite(3,HIGH);//square wave } else { digitalWrite(3,LOW);//square wave } y=y+1; if ( y>10) { n=n+1; y=1; OCR1A=data[n];//pwm OCR1B=n*8;//ramp wave //digitalWrite(3,data[n]);//square wave if (data[n]>=125) { digitalWrite(3,HIGH);//square wave } else { digitalWrite(3,LOW);//square wave } } } else { OCR1A=data[n]; OCR1B=n*8;//ramp wave digitalWrite(3,data[n]);//square wave n=n+1; } // if (n>23) { n=0; OCR0A=val; } }
Программа должна быть загружена в Ардуино с помощью программного обеспечения Arduino IDE. С USB-кабелем, подключенным между Arduino и ПК, значение частоты можно посмотреть на дисплее LCD1, а на последовательном плоттере в Arduino IDE посмотреть форму сигнала.
Переключатель S1, подключенный к контакту 2 платы Board1, используется для переключения отображения между LCD1 и последовательным плоттером в Arduino IDE. Если контакт 2 заземлен, осциллограммы (синусоидальный, квадратный и пилообразный сигнал) можно просматривать на последовательном плоттере, как на цифровом осциллографе:
Каждая форма сигнала имеет величину около 5 В. Таким образом, синусоидальная волна изменяется от 0 до 5 В и не переходит в отрицательную.
Подключения LCD1 выполняются на печатной плате с помощью 16-контактной гребенки. Резистор на 470 Ом (R1), подключенный к выводу 15, используется для подсветки LCD1. Питание для ЖК-дисплея берется с контактов 5В и Gnd платы Arduino.
USB-кабель используется для подключения Arduino к ПК или ноутбуку. После загрузки программы плату Arduino и LCD1 можно запитать от адаптера / аккумулятора напряжением 9 вольт.
Строительство и испытания
Компоновка печатной платы (см. плата своими руками) генератора частоты и расположение его компонентов показано на следующем рисунке:
После сборки схемы на печатной плате загрузите исходный код на плату Arduino. Отсоедините плату от компьютера и подключите ее к источнику питания 9 В через разъем CON1.
Вы можете просмотреть сгенерированное значение частоты на ЖК-дисплее, разомкнув переключатель S1, или проверить различные формы сигналов на последовательном плоттере, замкнув S1.
