- Co to jest generator funkcji DDS?
- Zrozumieć działanie układu scalonego generatora funkcyjnego AD9833
- Komponenty wymagane do zbudowania generatora funkcji opartego na AD9833
- Generator funkcji oparty na AD9833 - Schemat ideowy
- Generator funkcji oparty na AD9833 - kod Arduino
- Testowanie generatora funkcyjnego opartego na AD9833
- Dalsze ulepszenia
Jeśli jesteś entuzjastą elektroniki, takim jak ja, który chce modyfikować różne obwody elektroniczne, posiadanie przyzwoitego generatora funkcji czasami staje się obowiązkowe. Ale posiadanie takiego jest problemem, ponieważ takie podstawowe wyposażenie może kosztować fortunę. Zbudowanie własnego sprzętu testowego to nie tylko tańsze, ale także świetny sposób na poszerzenie wiedzy.
W tym artykule zamierzamy zbudować prosty generator sygnału z Arduino i modułem generatora funkcyjnego AD9833 DDS, który może wytwarzać fale sinusoidalne, kwadratowe i trójkątne o maksymalnej częstotliwości 12 MHz na wyjściu. I na koniec przetestujemy częstotliwość wyjściową za pomocą naszego oscyloskopu.
Wcześniej zbudowaliśmy prosty generator fal sinusoidalnych, generator fal prostokątnych i generator fal trójkątnych za pomocą podstawowych obwodów analogowych. Możesz je sprawdzić, jeśli szukasz podstawowych obwodów generatora przebiegów. Ponadto, jeśli chcesz zbudować tańszy generator funkcji Arduino bez użycia modułu AD9833, możesz sprawdzić projekt DIY Arduino Waveform Generator.
Co to jest generator funkcji DDS?
Jak sama nazwa wskazuje, generator funkcyjny to urządzenie, które po ustawieniu może wyprowadzać określony przebieg o określonej częstotliwości. Załóżmy na przykład, że masz filtr LC, dla którego chcesz przetestować swoją odpowiedź częstotliwościową wyjściową, możesz to łatwo zrobić za pomocą generatora funkcji. Wszystko, co musisz zrobić, to ustawić żądaną częstotliwość wyjściową i kształt fali, a następnie możesz zmniejszyć lub zwiększyć, aby przetestować odpowiedź. To był tylko jeden przykład, możesz z nim zrobić więcej w miarę wydłużania się listy.
DDS to skrót od Direct Digital Synthesis. Jest to rodzaj generatora przebiegów, który wykorzystuje przetworniki cyfrowo- analogowe (DAC) do budowania sygnału od podstaw. Ta metoda jest szczególnie używana do generowania fali sinusoidalnej. Ale układ scalony, którego używamy, może wytwarzać sygnały prostokątne lub trójkątne. Operacje, które miały miejsce wewnątrz układu DDS, są cyfrowe, więc może on bardzo szybko przełączać częstotliwość lub bardzo szybko przełączać się z jednego sygnału na inny. To urządzenie ma wysoką rozdzielczość częstotliwości i szerokie spektrum częstotliwości.
Zrozumieć działanie układu scalonego generatora funkcyjnego AD9833
Sercem naszego projektu jest układ scalony programowalnego generatora przebiegów AD9833, który został zaprojektowany i opracowany przez urządzenia analogowe. Jest to programowalny generator przebiegów o małej mocy, zdolny do wytwarzania fal sinusoidalnych, trójkątnych i prostokątnych o maksymalnej częstotliwości 12 MHz. Jest to bardzo wyjątkowy układ scalony, który jest w stanie zmienić częstotliwość wyjściową i fazę za pomocą tylko oprogramowania. Posiada 3-przewodowy interfejs SPI, dlatego komunikacja z tym układem jest bardzo prosta i łatwa. Schemat funkcjonalny tego układu scalonego przedstawiono poniżej.
Działanie tego układu scalonego jest bardzo proste. Jeśli spojrzymy na powyższy schemat bloku funkcjonalnego, zauważymy, że mamy akumulator fazowy, którego zadaniem jest przechowywanie wszystkich możliwych wartości cyfrowych przebiegu sinusoidalnego, począwszy od 0 do 2π. Następnie mamy SIN ROM, którego zadaniem jest konwersja informacji o fazie, które można później bezpośrednio odwzorować na amplitudę. SIN ROM wykorzystuje cyfrowe informacje o fazie jako adres do tabeli przeglądowej i przekształca informacje o fazie na amplitudę. I na koniec mamy 10-bitowy przetwornik cyfrowo-analogowy, którego zadaniem jest odbieranie danych cyfrowych z SIN ROM i zamiana ich na odpowiednie napięcia analogowe, czyli to, co otrzymujemy z wyjścia. Na wyjściu mamy również przełącznik, który możemy włączyć lub wyłączyć za pomocą niewielkiego kodu oprogramowania. Porozmawiamy o tym w dalszej części artykułu.Szczegóły, które widzisz powyżej, są bardzo uproszczoną wersją tego, co dzieje się wewnątrz układu scalonego, a większość szczegółów, które widzisz powyżej, pochodzi z arkusza danych AD9833, możesz również sprawdzić, aby uzyskać dalsze informacje.
Komponenty wymagane do zbudowania generatora funkcji opartego na AD9833
Elementy wymagane do zbudowania generatora funkcyjnego opartego na AD9833 są wymienione poniżej. Zaprojektowaliśmy ten obwód z bardzo ogólnymi komponentami, co sprawia, że proces replikacji jest bardzo łatwy.
- Arduino Nano - 1
- Generator funkcji DDS AD9833 - 1
- Wyświetlacz OLED 128 X 64 - 1
- Generic Rotary Encoder - 1
- Gniazdo lufy DC - 1
- Regulator napięcia LM7809 - 1
- Kondensator 470uF - 1
- Kondensator 220uF - 1
- Kondensator 104pF - 1
- Rezystor 10 K - 6
- Przełączniki dotykowe - 4
- Zacisk śrubowy 5,04 mm - 1
- Nagłówek żeński - 1
- Źródło zasilania 12 V - 1
Generator funkcji oparty na AD9833 - Schemat ideowy
Pełny schemat obwodu dla AD9833 i generatora funkcyjnego opartego na Arduino pokazano poniżej.
Zamierzamy użyć AD9833 z Arduino do wygenerowania pożądanej częstotliwości. W tej sekcji wyjaśnimy wszystkie szczegóły za pomocą schematu; pozwólcie, że przedstawię wam krótki przegląd tego, co dzieje się z obwodem. Zacznijmy od modułu AD9833. Moduł AD9833 jest modułem generatora funkcji i jest połączony z Arduino zgodnie ze schematem. Do zasilania obwodu używamy układu scalonego regulatora napięcia LM7809 z porządnym kondensatorem odsprzęgającym, jest to konieczne, ponieważ szum zasilania może zakłócać sygnał wyjściowy, powodując niepożądane wyjście. Jak zawsze, Arduino działa jako mózg dla tego projektu. Aby wyświetlić ustawioną częstotliwość i inne cenne informacje, podłączyliśmy moduł wyświetlacza OLED 128 X 64. Aby zmienić zakres częstotliwości, używamy trzech przełączników. Pierwszy ustawia częstotliwość na Hz, drugi ustawia częstotliwość wyjściową na KHz, a trzeci ustawia częstotliwość na MHz, mamy też inny przycisk, którym możemy włączyć lub wyłączyć wyjście. Wreszcie mamy enkoder obrotowy,i musimy dołączyć do niego jakiś rezystor podciągający, w przeciwnym razie te przełączniki nie będą działać, ponieważ sprawdzamy zdarzenie naciśnięcia przycisku w metodzie pulowania. Enkoder obrotowy służy do zmiany częstotliwości, a przełącznik dotykowy wewnątrz enkodera obrotowego służy do wyboru ustawionego przebiegu.
Generator funkcji oparty na AD9833 - kod Arduino
Pełny kod użyty w tym projekcie znajduje się na dole tej strony. Po dodaniu wymaganych plików nagłówkowych i plików źródłowych powinieneś być w stanie bezpośrednio skompilować plik Arduino. Możesz pobrać bibliotekę Ad9833 Arduino i inne biblioteki z linku podanego poniżej lub możesz użyć metody zarządcy tablicy, aby zainstalować bibliotekę.
- Pobierz bibliotekę AD9833 autorstwa Billa Williamsa
- Pobierz bibliotekę SSD1306 OLED firmy Adafruit
- Pobierz bibliotekę Adafruit GFX
Wyjaśnienie kodu w pliku ino. plik jest następujący. Najpierw dołączamy wszystkie wymagane biblioteki. Biblioteka modułu AD9833 DDS jest poprzedzona biblioteką OLED, a do niektórych obliczeń wymagana jest biblioteka matematyczna.
#include // LIbrary dla modułu AD9833 #include
Następnie definiujemy wszystkie niezbędne piny wejściowe i wyjściowe dla przycisków, przełącznika, enkodera obrotowego i diod OLED.
# zdefiniować SCREEN_WIDATA_PINH 128 // Szerokość wyświetlacza OLED w pikselach # zdefiniować SCREEN_HEIGHT 64 // Wysokość wyświetlacza OLED w pikselach # zdefiniować SET_FREQUENCY_HZ A2 // Przycisk do ustawienia częstotliwości w Hz # zdefiniuj SET_FREQUENCY_KHZ A3 // Przycisk do ustawiania częstotliwości w khz A6 // Przycisk do ustawiania częstotliwości w MHz #define ENABLE_DISABLE_OUTPUT_PIN A7 // Przycisk do włączania / wyłączania wyjścia #define FNC_PIN 4 // Fsync wymagana przez moduł AD9833 # zdefiniować CLK_PIN 8 // Pin zegara enkodera # zdefiniować DATA_PIN 7 / / Pin danych enkodera #define BTN_PIN 9 // Wewnętrzny przycisk enkodera
Następnie definiujemy wszystkie niezbędne zmienne, które są wymagane w tym kodzie. Najpierw definiujemy licznik zmiennej całkowitej, który będzie przechowywać wartość enkodera obrotowego. Kolejne dwie zmienne clockPin i clockPinState przechowują statuetkę pinu, która jest wymagana do zrozumienia kierunku kodera. Mamy zmienną czasową, która przechowuje aktualne wartości licznika czasu, ta zmienna jest używana do odbijania przycisków. Następnie mamy nieoznaczoną długą zmienną moduleFrequency, która przechowuje obliczoną częstotliwość, która ma zostać zastosowana. Następnie mamy opóźnienie odbicia. To opóźnienie można dostosować w razie potrzeby. Następnie mamy trzy zmienne boolowskie set_frequency_hz,set_frequency_Khz i set_frequency_Mhz te trzy zmienne służą do określenia aktualnego ustawienia modułu. Porozmawiamy o tym bardziej szczegółowo w dalszej części artykułu. Następnie mamy zmienną przechowującą stan przebiegu wyjściowego, domyślnym przebiegiem wyjściowym jest sinusoida. I wreszcie mamy zmienną encoder_btn_count, która przechowuje liczbę przycisków enkodera, która jest używana do ustawiania przebiegu wyjściowego.
int counter = 1; // Ta wartość licznika wzrośnie lub zmniejszy się, jeśli enkoder obrotowy jest włączony int clockPin; // Symbol zastępczy dla statusu pinów używany przez enkoder obrotowy int clockPinState; // Symbol zastępczy dla statusu pinów używany przez enkoder obrotowy unsigned long time = 0; // Służy do usuwania wartości long unsigned moduleFrequency; // używane do ustawiania częstotliwości wyjściowej long debounce = 220; // Opóźnienie odbicia bool btn_state; // używane do włączania wyłączania wyjścia modułu AD98333 bool set_frequency_hz = 1; // Defult częstotliwość modułu AD9833 bool set_frequency_khz; bool set_frequency_mhz; String waveSelect = "SIN"; // Przebieg uruchomienia modułu int encoder_btn_count = 0; // użyty do sprawdzenia przycisku enkodera naciśnij Dalej, mamy nasze dwa obiekty, jeden dla wyświetlacza OLED, a drugi dla modułu AD9833.Wyświetlacz Adafruit_SSD1306 (SCREEN_WIDATA_PINH, SCREEN_HEIGHT, & Wire, -1); Gen AD9833 (FNC_PIN);
Następnie mamy naszą funkcję setup (), w tej funkcji setup zaczynamy od włączenia Serial do debugowania. Inicjalizujemy moduł AD9833 za pomocą metody begin (). Następnie ustawiamy wszystkie przypisane piny enkodera obrotowego jako Input. I przechowujemy wartość pinu zegara w zmiennej clockPinState, jest to niezbędny krok dla enkodera obrotowego.
Następnie ustawiamy wszystkie piny przycisków jako dane wejściowe i włączamy wyświetlacz OLED za pomocą metody display.begin () , a także sprawdzamy ewentualne błędy za pomocą instrukcji if . Kiedy to zrobimy, czyścimy wyświetlacz i drukujemy startowy ekran powitalny, dodajemy opóźnienie 2 sekund, które jest również opóźnieniem dla ekranu powitalnego, i na koniec wywołujemy funkcję update_display (), która czyści ekran i aktualizuje wyświetlić ponownie. Szczegóły metody update_display () zostaną omówione w dalszej części artykułu.
void setup () {Serial.begin (9600); // Włącz Serial @ 9600 bodów gen.Begin (); // To MUSI być pierwsza komenda po zadeklarowaniu pinMode obiektu AD9833 (CLK_PIN, INPUT); // Ustawianie pinów jako wejściowych pinMode (DATA_PIN, INPUT); pinMode (BTN_PIN, INPUT_PULLUP); clockPinState = digitalRead (CLK_PIN); pinMode (SET_FREQUENCY_HZ, INPUT); // Ustawienie pinów jako wejścia pinMode (SET_FREQUENCY_KHZ, INPUT); pinMode (SET_FREQUENCY_MHZ, INPUT); pinMode (ENABLE_DISABLE_OUTPUT_PIN, INPUT); if (! display.begin (SSD1306_SWITCHCAPVCC, 0x3C)) {// Adres 0x3D dla 128x64 Serial.println (F ("alokacja SSD1306 nie powiodła się")); dla (;;); } display.clearDisplay (); // Wyczyść ekran display.setTextSize (2); // Ustaw rozmiar tekstu display.setTextColor (WHITE); // ustaw kolorowy wyświetlacz LCD.setCursor (30, 0); // Ustaw pozycję kursora display.println ("AD9833"); // Wydrukuj ten wyświetlacz tekstowy.setCursor (17, 20); // Ustaw pozycję kursora display.println ("Funkcja"); // Wydrukuj ten tekst display.setCursor (13, 40); // Ustaw pozycję kursora display.println ("Generator"); // Wydrukuj ten tekst display.display (); // Zaktualizuj opóźnienie wyświetlania (2000); // Opóźnienie 2 SEC update_display (); // Zadzwoń do funkcji update_display}
Następnie mamy funkcję loop (), wszystkie główne funkcje są zapisane w sekcji pętli.
Najpierw odczytujemy pin Clock z Rotary encoder i przechowujemy go w zmiennej clockPin, którą zadeklarowaliśmy wcześniej. Następnie w instrukcji if sprawdzamy, czy poprzednia wartość kołka i aktualna wartość kołka są podobne, czy nie, a także sprawdzamy aktualną wartość kołka. Jeśli to wszystko prawda, sprawdzamy pin danych, jeśli prawda, oznacza to, że koder obraca się w kierunku przeciwnym do ruchu wskazówek zegara i zmniejszamy wartość licznika za pomocą polecenia counter. W przeciwnym razie zwiększamy wartość licznika poleceniem counter ++. Na koniec umieściliśmy kolejną instrukcję if , aby ustawić minimalną wartość na 1. Następnie aktualizujemy clockPinState bieżącym clockPinwartość do wykorzystania w przyszłości.
void loop () {clockPin = digitalRead (CLK_PIN); if (clockPin! = clockPinState && clockPin == 1) {if (digitalRead (DATA_PIN)! = clockPin) {licznik -; } else {licznik ++; // Enkoder obraca się w prawo, więc zwiększ} if (licznik <1) licznik = 1; Serial.println (licznik); update_display (); }
Następnie mamy nasz kod do wykrywania naciśnięcia przycisku. W tej sekcji wykryliśmy przycisk wewnątrz kodera za pomocą zagnieżdżonych instrukcji if, if (digitalRead (BTN_PIN) == LOW && millis () - time> denounce), w tej instrukcji najpierw sprawdzamy, czy przycisk pin jest niski lub nie, jeśli jest niski, to jest wciśnięty. Następnie ponownie sprawdzamy wartość timera z opóźnieniem odbicia, jeśli obie instrukcje są prawdziwe, to deklarujemy, że było to udane naciśnięcie przycisku, jeśli tak, zwiększamy wartość encoder_btn_count. Następnie deklarujemy inną instrukcję if, aby ustawić maksymalną wartość licznika na 2, potrzebujemy jej, ponieważ używamy jej do ustawienia przebiegu wyjściowego.Kolejne trzy instrukcje if to robią, jeśli wartość wynosi zero, wybierany jest przebieg sinusoidalny, jeśli jest to jeden, jest to przebieg prostokątny, a jeśli wartość wynosi 2, jest to fala trójkątna. We wszystkich trzech instrukcjach if aktualizujemy wyświetlacz za pomocą funkcji update_display () . Na koniec aktualizujemy zmienną czasową o aktualną wartość licznika timera.
// Jeśli wykryjemy sygnał LOW, przycisk zostanie naciśnięty if (digitalRead (BTN_PIN) == LOW && millis () - time> debounce) {encoder_btn_count ++; // Zwiększ wartości, jeśli (encoder_btn_count> 2) // jeśli wartość jest większa niż 2, zresetuj ją do 0 {encoder_btn_count = 0; } if (encoder_btn_count == 0) {// jeśli wartość wynosi 0, wybrana jest fala sinusoidalna waveSelect = "SIN"; // zaktualizuj zmienną łańcuchową wartością sinus update_display (); // zaktualizuj wyświetlacz} if (encoder_btn_count == 1) {// jeśli wybrano 1 falę prostokątną waveSelect = "SQR"; // zaktualizuj zmienną łańcuchową o wartość SQR update_display (); // zaktualizuj wyświetlacz} if (encoder_btn_count == 2) {// jeśli wartość wynosi 1 Wybrano falę trójkątną waveSelect = "TRI"; // zaktualizuj zmienną łańcuchową wartością TRI update_display ();// zaktualizuj wyświetlacz} time = millis (); // zaktualizuj zmienną czasu}
Następnie definiujemy cały niezbędny kod, który jest wymagany do skonfigurowania wszystkich przycisków z opóźnieniem odbicia. Ponieważ przyciski są podłączone do analogowych pinów Arduino, używamy polecenia odczytu analogowego, aby zidentyfikować naciśnięcie przycisku, jeśli wartość odczytu analogowego spadnie poniżej 30, następnie wykrywamy jego udane naciśnięcie przycisku i czekamy 200 ms na sprawdź, czy jest to faktyczne naciśnięcie przycisku, czy tylko dźwięk. Jeśli to stwierdzenie jest prawdziwe, przypisujemy zmiennym logicznym wartości, które są używane do ustawiania wartości Hz, Khz i Mhz generatora funkcji. Następnie aktualizujemy wyświetlacz i aktualizujemy zmienną czasową. Robimy to dla wszystkich czterech przycisków połączonych z Arduino.
if (analogRead (SET_FREQUENCY_HZ) <30 && millis () - czas> odbicia) {set_frequency_hz = 1; // aktualizacja wartości boolowskich set_frequency_khz = 0; set_frequency_mhz = 0; update_display (); // aktualizuj czas wyświetlania = millis (); // aktualizuj zmienną czasu} if (analogRead (SET_FREQUENCY_KHZ) <30 && millis () - time> debounce) {set_frequency_hz = 0; // zaktualizuj wartości logiczne set_frequency_khz = 1; set_frequency_mhz = 0; moduleFrequency = licznik * 1000; update_display (); // aktualizuj czas wyświetlania = millis (); // aktualizuj zmienną czasu} if (analogRead (SET_FREQUENCY_MHZ) <30 && millis () - time> debounce) {// sprawdź pin analogowy z opóźnieniem odbicia set_frequency_hz = 0; // zaktualizuj wartości logiczne set_frequency_khz = 0; set_frequency_mhz = 1; moduleFrequency = counter * 1000000; update_display ();// zaktualizuj czas wyświetlania = millis (); // zaktualizuj zmienną czasu} if (analogRead (ENABLE_DISABLE_OUTPUT_PIN) <30 && millis () - time> debounce) {// sprawdź analogowy pin z opóźnieniem odbicia btn_state =! btn_state; // Odwróć stan przycisku gen.EnableOutput (btn_state); // Włącz / Wyłącz wyjście generatora funkcji w zależności od stanu przycisku update_display (); // zaktualizuj czas wyświetlania = millis (); // zaktualizuj zmienną czasu}}// zaktualizuj zmienną czasu}}// zaktualizuj zmienną czasu}}
Wreszcie mamy funkcję update_display (). W tej funkcji zrobiliśmy o wiele więcej niż tylko aktualizację tego wyświetlacza, ponieważ pewnej części wyświetlacza nie można zaktualizować w OLED. Aby go zaktualizować, musisz przemalować go nowymi wartościami. To znacznie utrudnia proces kodowania.
Wewnątrz tej funkcji zaczynamy od wyczyszczenia wyświetlacza. Następnie ustawiamy wymagany rozmiar tekstu. Następnie ustawiamy kursor i wypisujemy generator funkcji za pomocą display.println ("Funkcja funkcji"); Komenda. Ponownie ustawiamy rozmiar tekstu na 2, a kursor na (0,20) za pomocą funkcji display.setCursor (0, 20).
Tutaj drukujemy informacje o tym, jaka to fala.
display.clearDisplay (); // Najpierw wyczyść wyświetlacz display.setTextSize (1); // ustaw tekst Size display.setCursor (10, 0); // Ustaw pozycję kursora display.println ("Generator funkcji"); // wypisz tekst display.setTextSize (2); // ustaw tekst Size display.setCursor (0, 20); // Ustaw pozycję kursora
Następnie sprawdzamy zmienne boolowskie pod kątem szczegółów częstotliwości i aktualizujemy wartość w zmiennej moduleFrequency. Robimy to dla wartości Hz, kHz i MHz. Następnie sprawdzamy zmienną waveSelect i identyfikujemy wybrany przebieg. Teraz mamy wartości do ustawienia typu fali i częstotliwości.
if (set_frequency_hz == 1 && set_frequency_khz == 0 && set_frequency_mhz == 0) {// sprawdź, czy wciśnięty jest przycisk do ustawiania częstotliwości w Hz moduleFrequency = licznik; // zaktualizuj zmienną moduleFrequency o aktualną wartość licznika} if (set_frequency_hz == 0 && set_frequency_khz == 1 && set_frequency_mhz == 0) {// sprawdź, czy naciśnięto przycisk ustawiania częstotliwości w kHz moduleFrequency = licznik * 1000; // zaktualizuj zmienną moduleFrequency o aktualną wartość licznika, ale pomnożymy 1000, aby ustawić ją na KHZ} if (set_frequency_hz == 0 && set_frequency_khz == 0 && set_frequency_mhz == 1) {// sprawdź czy przycisk do ustawiania częstotliwości w MHz jest wciśnięty moduleFrequency = licznik * 1000000; if (moduleFrequency> 12000000) {moduleFrequency = 12000000;// nie pozwól, aby częstotliwość była większa niż 12Mhz counter = 12; }} if (waveSelect == "SIN") {// Wybrano sinusoidę display.println ("SIN"); gen.ApplySignal (SINE_WAVE, REG0, moduleFrequency); Serial.println (moduleFrequency); } if (waveSelect == "SQR") {// Wybrano falę Sqr display.println ("SQR"); gen.ApplySignal (SQUARE_WAVE, REG0, moduleFrequency); Serial.println (moduleFrequency); } if (waveSelect == "TRI") {// Potrójna fala jest wybrana display.println ("TRI"); gen.ApplySignal (TRIANGLE_WAVE, REG0, moduleFrequency); // zaktualizuj moduł AD9833. Serial.println (moduleFrequency); }} if (waveSelect == "SQR") {// Wybrano falę Sqr display.println ("SQR"); gen.ApplySignal (SQUARE_WAVE, REG0, moduleFrequency); Serial.println (moduleFrequency); } if (waveSelect == "TRI") {// Potrójna fala jest wybrana display.println ("TRI"); gen.ApplySignal (TRIANGLE_WAVE, REG0, moduleFrequency); // zaktualizuj moduł AD9833. Serial.println (moduleFrequency); }} if (waveSelect == "SQR") {// Wybrano falę Sqr display.println ("SQR"); gen.ApplySignal (SQUARE_WAVE, REG0, moduleFrequency); Serial.println (moduleFrequency); } if (waveSelect == "TRI") {// Wybrano potrójną falę display.println ("TRI"); gen.ApplySignal (TRIANGLE_WAVE, REG0, moduleFrequency); // zaktualizuj moduł AD9833. Serial.println (moduleFrequency); }
Ponownie ustawiamy kursor i aktualizujemy wartości liczników. Ponownie sprawdzamy wartość logiczną, aby zaktualizować zakres częstotliwości na wyświetlaczu, musimy to zrobić, ponieważ zasada działania OLED jest bardzo dziwna.
display.setCursor (45, 20); display.println (licznik); // wydrukuj informacje licznika na wyświetlaczu. if (set_frequency_hz == 1 && set_frequency_khz == 0 && set_frequency_mhz == 0) {display.setCursor (90, 20); display.println ("Hz"); // wypisz Hz na wyświetlaczu display.display (); // kiedy wszystko ustawione, zaktualizuj wyświetlacz} if (set_frequency_hz == 0 && set_frequency_khz == 1 && set_frequency_mhz == 0) {display.setCursor (90, 20); display.println ("Khz"); display.display (); // kiedy wszystko ustawione, zaktualizuj wyświetlacz} if (set_frequency_hz == 0 && set_frequency_khz == 0 && set_frequency_mhz == 1) {display.setCursor (90, 20); display.println ("Mhz"); display.display (); // kiedy wszystko ustawione, zaktualizuj wyświetlacz}
Następnie sprawdzamy zmienną naciśnięcia przycisku, aby wydrukować / wyłączyć wyjście na OLED. Znowu należy to zrobić ze względu na moduł OLED.
if (btn_state) {display.setTextSize (1); display.setCursor (65, 45); display.print ("Wyjście WŁ."); // wypisuje wyjście na display.display (); display.setTextSize (2); } else {display.setTextSize (1); display.setCursor (65, 45); display.print ("Wyjście wyłączone"); // wypisuje wyjście na display.display (); display.setTextSize (2); }
Oznacza to koniec naszego procesu kodowania. Jeśli jesteś zdezorientowany w tym momencie, możesz sprawdzić komentarze w kodzie, aby uzyskać dalsze zrozumienie.
Testowanie generatora funkcyjnego opartego na AD9833
Aby przetestować obwód, używana jest powyższa konfiguracja. Jak widać, podłączyliśmy zasilacz 12V DC do gniazda cylindrycznego DC i podłączyliśmy oscyloskop Hantek do wyjścia układu. Podłączyliśmy również oscyloskop do laptopa, aby wizualizować i mierzyć częstotliwość wyjściową.
Po wykonaniu tej czynności ustawiamy częstotliwość wyjściową na 5 kHz za pomocą enkodera obrotowego i testujemy wyjściową falę sinusoidalną i na pewno jest to fala sinusoidalna 5 kHz na wyjściu.
Następnie zmieniliśmy przebieg wyjściowy na trójkątny, ale częstotliwość pozostała taka sama, przebieg wyjściowy pokazano poniżej.
Następnie zmieniliśmy wyjście na falę prostokątną i obserwowaliśmy wyjście i była to idealna fala prostokątna.
Zmieniliśmy również zakresy częstotliwości i przetestowaliśmy wyjście i działało dobrze.
Dalsze ulepszenia
Ten obwód jest tylko potwierdzeniem koncepcji i wymaga dalszych ulepszeń. Po pierwsze, potrzebujemy dobrej jakości PCB i jakiegoś dobrej jakości złącza BNC na wyjście, w przeciwnym razie nie możemy uzyskać wyższej częstotliwości. Amplituda modułu jest bardzo niska, więc aby to zwiększyć, potrzebujemy kilku obwodów wzmacniacza operacyjnego do wzmocnienia napięcia wyjściowego. W celu zmiany amplitudy wyjściowej można podłączyć potencjometr. Można podłączyć przełącznik do kompensacji sygnału; jest to również funkcja obowiązkowa. Co więcej, kod wymaga wielu ulepszeń, ponieważ jest trochę błędny. Wreszcie wyświetlacze OLED wymagają zmiany, w przeciwnym razie nie będzie można napisać zrozumiałego kodu.
To oznacza koniec tego samouczka. Mam nadzieję, że spodobał Ci się artykuł i nauczyłeś się czegoś nowego. Jeśli masz jakieś pytania dotyczące artykułu, możesz je zostawić w sekcji komentarzy poniżej lub możesz skorzystać z naszego Forum Elektroniki.